1 <?php
2 /**
3  * PHPMailer - PHP email creation and transport
class.
4  * PHP Version
5
5  * @package PHPMailer
6  * @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
7  * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
8  * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
9  * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
10  * @author Brent R. Matzelle (original founder)
11  * @copyright
2012 - 2014 Marcus Bointon
12  * @copyright
2010 - 2012 Jim Jagielski
13  * @copyright
2004 - 2009 Andy Prevost
14  * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
15  * @note This program
is distributed in the hope that it will be useful - WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  * FITNESS FOR A PARTICULAR PURPOSE.
18  */
19
20 /**
21  * PHPMailer - PHP email creation and transport
class.
22  * @package PHPMailer
23  * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
24  * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
25  * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
26  * @author Brent R. Matzelle (original founder)
27  */

28 class
PHPMailer
29 {
30     
/**
31      * The PHPMailer Version number.
32      * @type
string
33      */

34     
public $Version = '5.2.9';
35
36     
/**
37      * Email priority.
38      * Options:
1 = High, 3 = Normal, 5 = low.
39      * @type integer
40      */

41     
public $Priority = 3;
42
43     
/**
44      * The character
set of the message.
45      * @type
string
46      */

47     
public $CharSet = 'iso-8859-1';
48
49     
/**
50      * The MIME Content-type of the message.
51      * @type
string
52      */

53     
public $ContentType = 'text/plain';
54
55     
/**
56      * The message encoding.
57      * Options:
"8bit", "7bit", "binary", "base64", and "quoted-printable".
58      * @type
string
59      */

60     
public $Encoding = '8bit';
61
62     
/**
63      * Holds the most recent mailer error message.
64      * @type
string
65      */

66     
public $ErrorInfo = '';
67
68     
/**
69      * The From email address
for the message.
70      * @type
string
71      */

72     
public $From = 'root@localhost';
73
74     
/**
75      * The From name of the message.
76      * @type
string
77      */

78     
public $FromName = 'Root User';
79
80     
/**
81      * The Sender email (Return-Path) of the message.
82      * If not empty, will be sent via -f to sendmail or
as 'MAIL FROM' in smtp mode.
83      * @type
string
84      */

85     
public $Sender = '';
86
87     
/**
88      * The Return-Path of the message.
89      * If empty, it will be
set to either From or Sender.
90      * @type
string
91      * @deprecated Email senders should never
set a return-path header;
92      * it
's the receiver's job (RFC5321 section 4.4), so this no longer does anything.
93      * @link https://tools.ietf.org/html/rfc5321#section-
4.4 RFC5321 reference
94      */

95     
public $ReturnPath = '';
96
97     
/**
98      * The Subject of the message.
99      * @type
string
100      */

101     
public $Subject = '';
102
103     
/**
104      * An HTML or plain text message body.
105      * If HTML then call isHTML(
true).
106      * @type
string
107      */

108     
public $Body = '';
109
110     
/**
111      * The plain-text message body.
112      * This body can be read
by mail clients that do not have HTML email
113      * capability such
as mutt & Eudora.
114      * Clients that can read HTML will view the normal Body.
115      * @type
string
116      */

117     
public $AltBody = '';
118
119     
/**
120      * An iCal message part body.
121      * Only supported
in simple alt or alt_inline message types
122      * To generate iCal events, use the bundled extras/EasyPeasyICS.php
class or iCalcreator
123      * @link http://sprain.ch/blog/downloads/php-
class-easypeasyics-create-ical-files-with-php/
124      * @link http://kigkonsult.se/iCalcreator/
125      * @type
string
126      */

127     
public $Ical = '';
128
129     
/**
130      * The complete compiled MIME message body.
131      * @access
protected
132      * @type
string
133      */

134     
protected $MIMEBody = '';
135
136     
/**
137      * The complete compiled MIME message headers.
138      * @type
string
139      * @access
protected
140      */

141     
protected $MIMEHeader = '';
142
143     
/**
144      * Extra headers that createHeader() doesn
't fold in.
145      * @type
string
146      * @access
protected
147      */

148     
protected $mailHeader = '';
149
150     
/**
151      * Word-wrap the message body to
this number of chars.
152      * Set to
0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance.
153      * @type integer
154      */

155     
public $WordWrap = 0;
156
157     
/**
158      * Which method to use to send mail.
159      * Options:
"mail", "sendmail", or "smtp".
160      * @type
string
161      */

162     
public $Mailer = 'mail';
163
164     
/**
165      * The path to the sendmail program.
166      * @type
string
167      */

168     
public $Sendmail = '/usr/sbin/sendmail';
169
170     
/**
171      * Whether mail() uses a fully sendmail-compatible MTA.
172      * One which supports sendmail
's "-oi -f" options.
173      * @type boolean
174      */

175     
public $UseSendmailOptions = true;
176
177     
/**
178      * Path to PHPMailer plugins.
179      * Useful
if the SMTP class is not in the PHP include path.
180      * @type
string
181      * @deprecated Should not be needed now there
is an autoloader.
182      */

183     
public $PluginDir = '';
184
185     
/**
186      * The email address that a reading confirmation should be sent to.
187      * @type
string
188      */

189     
public $ConfirmReadingTo = '';
190
191     
/**
192      * The hostname to use
in Message-Id and Received headers
193      * and
as default HELO string.
194      * If empty, the
value returned
195      *
by SERVER_NAME is used or 'localhost.localdomain'.
196      * @type
string
197      */

198     
public $Hostname = '';
199
200     
/**
201      * An ID to be used
in the Message-Id header.
202      * If empty, a unique id will be generated.
203      * @type
string
204      */

205     
public $MessageID = '';
206
207     
/**
208      * The message Date to be used
in the Date header.
209      * If empty, the current date will be added.
210      * @type
string
211      */

212     
public $MessageDate = '';
213
214     
/**
215      * SMTP hosts.
216      * Either a single hostname or multiple semicolon-delimited hostnames.
217      * You can also specify a different port
218      *
for each host by using this format: [hostname:port]
219      * (e.g.
"smtp1.example.com:25;smtp2.example.com").
220      * You can also specify encryption type,
for example:
221      * (e.g.
"tls://smtp1.example.com:587;ssl://smtp2.example.com:465").
222      * Hosts will be tried
in order.
223      * @type
string
224      */

225     
public $Host = 'localhost';
226
227     
/**
228      * The
default SMTP server port.
229      * @type integer
230      * @TODO Why
is this needed when the SMTP class takes care of it?
231      */

232     
public $Port = 25;
233
234     
/**
235      * The SMTP HELO of the message.
236      * Default
is $Hostname.
237      * @type
string
238      * @see PHPMailer::$Hostname
239      */

240     
public $Helo = '';
241
242     
/**
243      * The secure connection prefix.
244      * Options:
"", "ssl" or "tls"
245      * @type
string
246      */

247     
public $SMTPSecure = '';
248
249     
/**
250      * Whether to use SMTP authentication.
251      * Uses the Username and Password properties.
252      * @type boolean
253      * @see PHPMailer::$Username
254      * @see PHPMailer::$Password
255      */

256     
public $SMTPAuth = false;
257
258     
/**
259      * SMTP username.
260      * @type
string
261      */

262     
public $Username = '';
263
264     
/**
265      * SMTP password.
266      * @type
string
267      */

268     
public $Password = '';
269
270     
/**
271      * SMTP auth type.
272      * Options are LOGIN (
default), PLAIN, NTLM, CRAM-MD5
273      * @type
string
274      */

275     
public $AuthType = '';
276
277     
/**
278      * SMTP realm.
279      * Used
for NTLM auth
280      * @type
string
281      */

282     
public $Realm = '';
283
284     
/**
285      * SMTP workstation.
286      * Used
for NTLM auth
287      * @type
string
288      */

289     
public $Workstation = '';
290
291     
/**
292      * The SMTP server timeout
in seconds.
293      * Default of
5 minutes (300sec) is from RFC2821 section 4.5.3.2
294      * @type integer
295      */

296     
public $Timeout = 300;
297
298     
/**
299      * SMTP
class debug output mode.
300      * Debug output level.
301      * Options:
302      * * `
0` No output
303      * * `
1` Commands
304      * * `
2` Data and commands
305      * * `
3` As 2 plus connection status
306      * * `
4` Low-level data output
307      * @type integer
308      * @see SMTP::$do_debug
309      */

310     
public $SMTPDebug = 0;
311
312     
/**
313      * How to handle debug output.
314      * Options:
315      * * `echo` Output plain-text
as-is, appropriate for CLI
316      * * `html` Output escaped, line breaks converted to `<br>`, appropriate
for browser output
317      * * `error_log` Output to error log
as configured in php.ini
318      *
319      * Alternatively, you can provide a callable expecting two
params: a message string and the debug level:
320      * <code>
321      * $mail->Debugoutput = function($str, $level) {echo
"debug level $level; message: $str";};
322      * </code>
323      * @type
string|callable
324      * @see SMTP::$Debugoutput
325      */

326     
public $Debugoutput = 'echo';
327
328     
/**
329      * Whether to keep SMTP connection open after each message.
330      * If
this is set to true then to close the connection
331      * requires an
explicit call to smtpClose().
332      * @type boolean
333      */

334     
public $SMTPKeepAlive = false;
335
336     
/**
337      * Whether to split multiple to addresses
into multiple messages
338      * or send them all
in one message.
339      * @type boolean
340      */

341     
public $SingleTo = false;
342
343     
/**
344      * Storage
for addresses when SingleTo is enabled.
345      * @type array
346      * @TODO This should really not be
public
347      */

348     
public $SingleToArray = array();
349
350     
/**
351      * Whether to generate VERP addresses
on send.
352      * Only applicable
when sending via SMTP.
353      * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path
354      * @link http://www.postfix.org/VERP_README.html Postfix VERP info
355      * @type boolean
356      */

357     
public $do_verp = false;
358
359     
/**
360      * Whether to allow sending messages with an empty body.
361      * @type boolean
362      */

363     
public $AllowEmpty = false;
364
365     
/**
366      * The
default line ending.
367      * @note The
default remains "\n". We force CRLF where we know
368      * it must be used via self::CRLF.
369      * @type
string
370      */

371     
public $LE = "\n";
372
373     
/**
374      * DKIM selector.
375      * @type
string
376      */

377     
public $DKIM_selector = '';
378
379     
/**
380      * DKIM Identity.
381      * Usually the email address used
as the source of the email
382      * @type
string
383      */

384     
public $DKIM_identity = '';
385
386     
/**
387      * DKIM passphrase.
388      * Used
if your key is encrypted.
389      * @type
string
390      */

391     
public $DKIM_passphrase = '';
392
393     
/**
394      * DKIM signing domain name.
395      * @example
'example.com'
396      * @type
string
397      */

398     
public $DKIM_domain = '';
399
400     
/**
401      * DKIM
private key file path.
402      * @type
string
403      */

404     
public $DKIM_private = '';
405
406     
/**
407      * Callback Action function name.
408      *
409      * The function that handles the result of the send email action.
410      * It
is called out by send() for each email sent.
411      *
412      * Value can be any php callable: http://www.php.net/is_callable
413      *
414      * Parameters:
415      * boolean $result result of the send action
416      *
string $to email address of the recipient
417      *
string $cc cc email addresses
418      *
string $bcc bcc email addresses
419      *
string $subject the subject
420      *
string $body the email body
421      *
string $from email address of sender
422      * @type
string
423      */

424     
public $action_function = '';
425
426     
/**
427      * What to put
in the X-Mailer header.
428      * Options: An empty
string for PHPMailer default, whitespace for none, or a string to use
429      * @type
string
430      */

431     
public $XMailer = '';
432
433     
/**
434      * An instance of the SMTP sender
class.
435      * @type SMTP
436      * @access
protected
437      */

438     
protected $smtp = null;
439
440     
/**
441      * The array of
'to' addresses.
442      * @type array
443      * @access
protected
444      */

445     
protected $to = array();
446
447     
/**
448      * The array of
'cc' addresses.
449      * @type array
450      * @access
protected
451      */

452     
protected $cc = array();
453
454     
/**
455      * The array of
'bcc' addresses.
456      * @type array
457      * @access
protected
458      */

459     
protected $bcc = array();
460
461     
/**
462      * The array of reply-to names and addresses.
463      * @type array
464      * @access
protected
465      */

466     
protected $ReplyTo = array();
467
468     
/**
469      * An array of all kinds of addresses.
470      * Includes all of $to, $cc, $bcc, $replyto
471      * @type array
472      * @access
protected
473      */

474     
protected $all_recipients = array();
475
476     
/**
477      * The array of attachments.
478      * @type array
479      * @access
protected
480      */

481     
protected $attachment = array();
482
483     
/**
484      * The array of custom headers.
485      * @type array
486      * @access
protected
487      */

488     
protected $CustomHeader = array();
489
490     
/**
491      * The most recent Message-ID (including angular brackets).
492      * @type
string
493      * @access
protected
494      */

495     
protected $lastMessageID = '';
496
497     
/**
498      * The message
's MIME type.
499      * @type
string
500      * @access
protected
501      */

502     
protected $message_type = '';
503
504     
/**
505      * The array of MIME boundary strings.
506      * @type array
507      * @access
protected
508      */

509     
protected $boundary = array();
510
511     
/**
512      * The array of available languages.
513      * @type array
514      * @access
protected
515      */

516     
protected $language = array();
517
518     
/**
519      * The number of errors encountered.
520      * @type integer
521      * @access
protected
522      */

523     
protected $error_count = 0;
524
525     
/**
526      * The S/MIME certificate file path.
527      * @type
string
528      * @access
protected
529      */

530     
protected $sign_cert_file = '';
531
532     
/**
533      * The S/MIME key file path.
534      * @type
string
535      * @access
protected
536      */

537     
protected $sign_key_file = '';
538
539     
/**
540      * The S/MIME password
for the key.
541      * Used only
if the key is encrypted.
542      * @type
string
543      * @access
protected
544      */

545     
protected $sign_key_pass = '';
546
547     
/**
548      * Whether to
throw exceptions for errors.
549      * @type boolean
550      * @access
protected
551      */

552     
protected $exceptions = false;
553
554     
/**
555      * Error severity: message only,
continue processing.
556      */

557     
const STOP_MESSAGE = 0;
558
559     
/**
560      * Error severity: message, likely ok to
continue processing.
561      */

562     
const STOP_CONTINUE = 1;
563
564     
/**
565      * Error severity: message, plus full stop, critical error reached.
566      */

567     
const STOP_CRITICAL = 2;
568
569     
/**
570      * SMTP RFC standard line ending.
571      */

572     
const CRLF = "\r\n";
573
574     
/**
575      * Constructor.
576      * @param boolean $exceptions Should we
throw external exceptions?
577      */

578     
public function __construct($exceptions = false)
579     {
580         $
this->exceptions = (boolean)$exceptions;
581     }
582
583     
/**
584      * Destructor.
585      */

586     
public function __destruct()
587     {
588         
if ($this->Mailer == 'smtp') { //close any open SMTP connection nicely
589             $
this->smtpClose();
590         }
591     }
592
593     
/**
594      * Call mail()
in a safe_mode-aware fashion.
595      * Also, unless sendmail_path points to sendmail (or something that
596      * claims to be sendmail), don
't pass params (not a perfect fix,
597      * but it will
do)
598      * @param
string $to To
599      * @param
string $subject Subject
600      * @param
string $body Message Body
601      * @param
string $header Additional Header(s)
602      * @param
string $params Params
603      * @access
private
604      * @
return boolean
605      */

606     
private function mailPassthru($to, $subject, $body, $header, $params)
607     {
608         
//Check overloading of mail function to avoid double-encoding
609         
if (ini_get('mbstring.func_overload') & 1) {
610             $subject = $
this->secureHeader($subject);
611         }
else {
612             $subject = $
this->encodeHeader($this->secureHeader($subject));
613         }
614         
if (ini_get('safe_mode') || !($this->UseSendmailOptions)) {
615             $result = @mail($to, $subject, $body, $header);
616         }
else {
617             $result = @mail($to, $subject, $body, $header, $
params);
618         }
619         
return $result;
620     }
621
622     
/**
623      * Output debugging info via user-defined method.
624      * Only generates output
if SMTP debug output is enabled (@see SMTP::$do_debug).
625      * @see PHPMailer::$Debugoutput
626      * @see PHPMailer::$SMTPDebug
627      * @param
string $str
628      */

629     
protected function edebug($str)
630     {
631         
if ($this->SMTPDebug <= 0) {
632             
return;
633         }
634         
//Avoid clash with built-in function names
635         
if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
636             call_user_func($
this->Debugoutput, $str, $this->SMTPDebug);
637             
return;
638         }
639         
switch ($this->Debugoutput) {
640             
case 'error_log':
641                 
//Don't output, just log
642                 error_log($str);
643                 
break;
644             
case 'html':
645                 
//Cleans up output a bit for a better looking, HTML-safe output
646                 echo htmlentities(
647                     preg_replace(
'/[\r\n]+/', '', $str),
648                     ENT_QUOTES,
649                     
'UTF-8'
650                 )
651                 .
"<br>\n";
652                 
break;
653             
case 'echo':
654             
default:
655                 
//Normalize line breaks
656                 $str = preg_replace(
'/(\r\n|\r|\n)/ms', "\n", $str);
657                 echo gmdate(
'Y-m-d H:i:s') . "\t" . str_replace(
658                     
"\n",
659                     
"\n \t ",
660                     trim($str)
661                 ) .
"\n";
662         }
663     }
664
665     
/**
666      * Sets message type to HTML or plain.
667      * @param boolean $isHtml True
for HTML mode.
668      * @
return void
669      */

670     
public function isHTML($isHtml = true)
671     {
672         
if ($isHtml) {
673             $
this->ContentType = 'text/html';
674         }
else {
675             $
this->ContentType = 'text/plain';
676         }
677     }
678
679     
/**
680      * Send messages
using SMTP.
681      * @
return void
682      */

683     
public function isSMTP()
684     {
685         $
this->Mailer = 'smtp';
686     }
687
688     
/**
689      * Send messages
using PHP's mail() function.
690      * @
return void
691      */

692     
public function isMail()
693     {
694         $
this->Mailer = 'mail';
695     }
696
697     
/**
698      * Send messages
using $Sendmail.
699      * @
return void
700      */

701     
public function isSendmail()
702     {
703         $ini_sendmail_path = ini_get(
'sendmail_path');
704
705         
if (!stristr($ini_sendmail_path, 'sendmail')) {
706             $
this->Sendmail = '/usr/sbin/sendmail';
707         }
else {
708             $
this->Sendmail = $ini_sendmail_path;
709         }
710         $
this->Mailer = 'sendmail';
711     }
712
713     
/**
714      * Send messages
using qmail.
715      * @
return void
716      */

717     
public function isQmail()
718     {
719         $ini_sendmail_path = ini_get(
'sendmail_path');
720
721         
if (!stristr($ini_sendmail_path, 'qmail')) {
722             $
this->Sendmail = '/var/qmail/bin/qmail-inject';
723         }
else {
724             $
this->Sendmail = $ini_sendmail_path;
725         }
726         $
this->Mailer = 'qmail';
727     }
728
729     
/**
730      * Add a
"To" address.
731      * @param
string $address
732      * @param
string $name
733      * @
return boolean true on success, false if address already used
734      */

735     
public function addAddress($address, $name = '')
736     {
737         
return $this->addAnAddress('to', $address, $name);
738     }
739
740     
/**
741      * Add a
"CC" address.
742      * @note: This function works with the SMTP mailer
on win32, not with the "mail" mailer.
743      * @param
string $address
744      * @param
string $name
745      * @
return boolean true on success, false if address already used
746      */

747     
public function addCC($address, $name = '')
748     {
749         
return $this->addAnAddress('cc', $address, $name);
750     }
751
752     
/**
753      * Add a
"BCC" address.
754      * @note: This function works with the SMTP mailer
on win32, not with the "mail" mailer.
755      * @param
string $address
756      * @param
string $name
757      * @
return boolean true on success, false if address already used
758      */

759     
public function addBCC($address, $name = '')
760     {
761         
return $this->addAnAddress('bcc', $address, $name);
762     }
763
764     
/**
765      * Add a
"Reply-to" address.
766      * @param
string $address
767      * @param
string $name
768      * @
return boolean
769      */

770     
public function addReplyTo($address, $name = '')
771     {
772         
return $this->addAnAddress('Reply-To', $address, $name);
773     }
774
775     
/**
776      * Add an address to one of the recipient arrays.
777      * Addresses that have been added already
return false, but do not throw exceptions
778      * @param
string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'
779      * @param
string $address The email address to send to
780      * @param
string $name
781      * @throws phpmailerException
782      * @
return boolean true on success, false if address already used or invalid in some way
783      * @access
protected
784      */

785     
protected function addAnAddress($kind, $address, $name = '')
786     {
787         
if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) {
788             $
this->setError($this->lang('Invalid recipient array') . ': ' . $kind);
789             $
this->edebug($this->lang('Invalid recipient array') . ': ' . $kind);
790             
if ($this->exceptions) {
791                 
throw new phpmailerException('Invalid recipient array: ' . $kind);
792             }
793             
return false;
794         }
795         $address = trim($address);
796         $name = trim(preg_replace(
'/[\r\n]+/', '', $name)); //Strip breaks and trim
797         
if (!$this->validateAddress($address)) {
798             $
this->setError($this->lang('invalid_address') . ': ' . $address);
799             $
this->edebug($this->lang('invalid_address') . ': ' . $address);
800             
if ($this->exceptions) {
801                 
throw new phpmailerException($this->lang('invalid_address') . ': ' . $address);
802             }
803             
return false;
804         }
805         
if ($kind != 'Reply-To') {
806             
if (!isset($this->all_recipients[strtolower($address)])) {
807                 array_push($
this->$kind, array($address, $name));
808                 $
this->all_recipients[strtolower($address)] = true;
809                 
return true;
810             }
811         }
else {
812             
if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
813                 $
this->ReplyTo[strtolower($address)] = array($address, $name);
814                 
return true;
815             }
816         }
817         
return false;
818     }
819
820     
/**
821      * Set the From and FromName properties.
822      * @param
string $address
823      * @param
string $name
824      * @param boolean $auto Whether to also
set the Sender address, defaults to true
825      * @throws phpmailerException
826      * @
return boolean
827      */

828     
public function setFrom($address, $name = '', $auto = true)
829     {
830         $address = trim($address);
831         $name = trim(preg_replace(
'/[\r\n]+/', '', $name)); //Strip breaks and trim
832         
if (!$this->validateAddress($address)) {
833             $
this->setError($this->lang('invalid_address') . ': ' . $address);
834             $
this->edebug($this->lang('invalid_address') . ': ' . $address);
835             
if ($this->exceptions) {
836                 
throw new phpmailerException($this->lang('invalid_address') . ': ' . $address);
837             }
838             
return false;
839         }
840         $
this->From = $address;
841         $
this->FromName = $name;
842         
if ($auto) {
843             
if (empty($this->Sender)) {
844                 $
this->Sender = $address;
845             }
846         }
847         
return true;
848     }
849
850     
/**
851      * Return the Message-ID header of the last email.
852      * Technically
this is the value from the last time the headers were created,
853      * but it
's also the message ID of the last sent message except in
854      * pathological cases.
855      * @
return string
856      */

857     
public function getLastMessageID()
858     {
859         
return $this->lastMessageID;
860     }
861
862     
/**
863      * Check that a
string looks like an email address.
864      * @param
string $address The email address to check
865      * @param
string $patternselect A selector for the validation pattern to use :
866      * * `auto` Pick strictest one automatically;
867      * * `pcre8` Use the squiloople.com pattern, requires PCRE >
8.0, PHP >= 5.3.2, 5.2.14;
868      * * `pcre` Use old PCRE implementation;
869      * * `php` Use PHP built-
in FILTER_VALIDATE_EMAIL; same as pcre8 but does not allow 'dotless' domains;
870      * * `html5` Use the pattern given
by the HTML5 spec for 'email' type form input elements.
871      * * `noregex` Don
't use a regex: super fast, really dumb.
872      * @
return boolean
873      * @
static
874      * @access
public
875      */

876     
public static function validateAddress($address, $patternselect = 'auto')
877     {
878         
if (!$patternselect or $patternselect == 'auto') {
879             
//Check this constant first so it works when extension_loaded() is disabled by safe mode
880             
//Constant was added in PHP 5.2.4
881             
if (defined('PCRE_VERSION')) {
882                 
//This pattern can get stuck in a recursive loop in PCRE <= 8.0.2
883                 
if (version_compare(PCRE_VERSION, '8.0.3') >= 0) {
884                     $patternselect =
'pcre8';
885                 }
else {
886                     $patternselect =
'pcre';
887                 }
888             } elseif (function_exists(
'extension_loaded') and extension_loaded('pcre')) {
889                 
//Fall back to older PCRE
890                 $patternselect =
'pcre';
891             }
else {
892                 
//Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension
893                 
if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
894                     $patternselect =
'php';
895                 }
else {
896                     $patternselect =
'noregex';
897                 }
898             }
899         }
900         
switch ($patternselect) {
901             
case 'pcre8':
902                 
/**
903                  * Uses the same RFC5322 regex
on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains.
904                  * @link http://squiloople.com/
2009/12/20/email-address-validation/
905                  * @copyright
2009-2010 Michael Rushton
906                  * Feel free to use and redistribute
this code. But please keep this copyright notice.
907                  */

908                 
return (boolean)preg_match(
909                     
'/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
910                     
'((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
911                     
'(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
912                     
'([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
913                     
'(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
914                     
'(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
915                     
'|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
916                     
'|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
917                     
'|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
918                     $address
919                 );
920             
case 'pcre':
921                 
//An older regex that doesn't need a recent PCRE
922                 
return (boolean)preg_match(
923                     
'/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' .
924                     
'[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' .
925                     
'(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' .
926                     
'@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' .
927                     
'(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' .
928                     
'[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' .
929                     
'::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' .
930                     
'[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' .
931                     
'::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
932                     
'|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD',
933                     $address
934                 );
935             
case 'html5':
936                 
/**
937                  * This
is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
938                  * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email)
939                  */

940                 
return (boolean)preg_match(
941                     
'/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
942                     
'[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
943                     $address
944                 );
945             
case 'noregex':
946                 
//No PCRE! Do something _very_ approximate!
947                 
//Check the address is 3 chars or longer and contains an @ that's not the first or last char
948                 
return (strlen($address) >= 3
949                     and strpos($address,
'@') >= 1
950                     and strpos($address,
'@') != strlen($address) - 1);
951             
case 'php':
952             
default:
953                 
return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL);
954         }
955     }
956
957     
/**
958      * Create a message and send it.
959      * Uses the sending method specified
by $Mailer.
960      * @throws phpmailerException
961      * @
return boolean false on error - See the ErrorInfo property for details of the error.
962      */

963     
public function send()
964     {
965         
try {
966             
if (!$this->preSend()) {
967                 
return false;
968             }
969             
return $this->postSend();
970         }
catch (phpmailerException $exc) {
971             $
this->mailHeader = '';
972             $
this->setError($exc->getMessage());
973             
if ($this->exceptions) {
974                 
throw $exc;
975             }
976             
return false;
977         }
978     }
979
980     
/**
981      * Prepare a message
for sending.
982      * @throws phpmailerException
983      * @
return boolean
984      */

985     
public function preSend()
986     {
987         
try {
988             $
this->mailHeader = '';
989             
if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
990                 
throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL);
991             }
992
993             
// Set whether the message is multipart/alternative
994             
if (!empty($this->AltBody)) {
995                 $
this->ContentType = 'multipart/alternative';
996             }
997
998             $
this->error_count = 0; // reset errors
999             $
this->setMessageType();
1000             
// Refuse to send an empty message unless we are specifically allowing it
1001             
if (!$this->AllowEmpty and empty($this->Body)) {
1002                 
throw new phpmailerException($this->lang('empty_message'), self::STOP_CRITICAL);
1003             }
1004
1005             $
this->MIMEHeader = $this->createHeader();
1006             $
this->MIMEBody = $this->createBody();
1007
1008             
// To capture the complete message when using mail(), create
1009             
// an extra header list which createHeader() doesn't fold in
1010             
if ($this->Mailer == 'mail') {
1011                 
if (count($this->to) > 0) {
1012                     $
this->mailHeader .= $this->addrAppend('To', $this->to);
1013                 }
else {
1014                     $
this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;');
1015                 }
1016                 $
this->mailHeader .= $this->headerLine(
1017                     
'Subject',
1018                     $
this->encodeHeader($this->secureHeader(trim($this->Subject)))
1019                 );
1020             }
1021
1022             
// Sign with DKIM if enabled
1023             
if (!empty($this->DKIM_domain)
1024                 && !empty($
this->DKIM_private)
1025                 && !empty($
this->DKIM_selector)
1026                 && file_exists($
this->DKIM_private)) {
1027                 $header_dkim = $
this->DKIM_Add(
1028                     $
this->MIMEHeader . $this->mailHeader,
1029                     $
this->encodeHeader($this->secureHeader($this->Subject)),
1030                     $
this->MIMEBody
1031                 );
1032                 $
this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . self::CRLF .
1033                     str_replace(
"\r\n", "\n", $header_dkim) . self::CRLF;
1034             }
1035             
return true;
1036
1037         }
catch (phpmailerException $exc) {
1038             $
this->setError($exc->getMessage());
1039             
if ($this->exceptions) {
1040                 
throw $exc;
1041             }
1042             
return false;
1043         }
1044     }
1045
1046     
/**
1047      * Actually send a message.
1048      * Send the email via the selected mechanism
1049      * @throws phpmailerException
1050      * @
return boolean
1051      */

1052     
public function postSend()
1053     {
1054         
try {
1055             
// Choose the mailer and send through it
1056             
switch ($this->Mailer) {
1057                 
case 'sendmail':
1058                 
case 'qmail':
1059                     
return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody);
1060                 
case 'smtp':
1061                     
return $this->smtpSend($this->MIMEHeader, $this->MIMEBody);
1062                 
case 'mail':
1063                     
return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
1064                 
default:
1065                     $sendMethod = $
this->Mailer.'Send';
1066                     
if (method_exists($this, $sendMethod)) {
1067                         
return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody);
1068                     }
1069
1070                     
return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
1071             }
1072         }
catch (phpmailerException $exc) {
1073             $
this->setError($exc->getMessage());
1074             $
this->edebug($exc->getMessage());
1075             
if ($this->exceptions) {
1076                 
throw $exc;
1077             }
1078         }
1079         
return false;
1080     }
1081
1082     
/**
1083      * Send mail
using the $Sendmail program.
1084      * @param
string $header The message headers
1085      * @param
string $body The message body
1086      * @see PHPMailer::$Sendmail
1087      * @throws phpmailerException
1088      * @access
protected
1089      * @
return boolean
1090      */

1091     
protected function sendmailSend($header, $body)
1092     {
1093         
if ($this->Sender != '') {
1094             
if ($this->Mailer == 'qmail') {
1095                 $sendmail = sprintf(
'%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
1096             }
else {
1097                 $sendmail = sprintf(
'%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
1098             }
1099         }
else {
1100             
if ($this->Mailer == 'qmail') {
1101                 $sendmail = sprintf(
'%s', escapeshellcmd($this->Sendmail));
1102             }
else {
1103                 $sendmail = sprintf(
'%s -oi -t', escapeshellcmd($this->Sendmail));
1104             }
1105         }
1106         
if ($this->SingleTo) {
1107             
foreach ($this->SingleToArray as $toAddr) {
1108                 
if (!@$mail = popen($sendmail, 'w')) {
1109                     
throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1110                 }
1111                 fputs($mail,
'To: ' . $toAddr . "\n");
1112                 fputs($mail, $header);
1113                 fputs($mail, $body);
1114                 $result = pclose($mail);
1115                 $
this->doCallback(
1116                     ($result ==
0),
1117                     array($toAddr),
1118                     $
this->cc,
1119                     $
this->bcc,
1120                     $
this->Subject,
1121                     $body,
1122                     $
this->From
1123                 );
1124                 
if ($result != 0) {
1125                     
throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1126                 }
1127             }
1128         }
else {
1129             
if (!@$mail = popen($sendmail, 'w')) {
1130                 
throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1131             }
1132             fputs($mail, $header);
1133             fputs($mail, $body);
1134             $result = pclose($mail);
1135             $
this->doCallback(($result == 0), $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From);
1136             
if ($result != 0) {
1137                 
throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1138             }
1139         }
1140         
return true;
1141     }
1142
1143     
/**
1144      * Send mail
using the PHP mail() function.
1145      * @param
string $header The message headers
1146      * @param
string $body The message body
1147      * @link http://www.php.net/manual/en/book.mail.php
1148      * @throws phpmailerException
1149      * @access
protected
1150      * @
return boolean
1151      */

1152     
protected function mailSend($header, $body)
1153     {
1154         $toArr = array();
1155         
foreach ($this->to as $toaddr) {
1156             $toArr[] = $
this->addrFormat($toaddr);
1157         }
1158         $to = implode(
', ', $toArr);
1159
1160         
if (empty($this->Sender)) {
1161             $
params = ' ';
1162         }
else {
1163             $
params = sprintf('-f%s', $this->Sender);
1164         }
1165         
if ($this->Sender != '' and !ini_get('safe_mode')) {
1166             $old_from = ini_get(
'sendmail_from');
1167             ini_set(
'sendmail_from', $this->Sender);
1168         }
1169         $result =
false;
1170         
if ($this->SingleTo && count($toArr) > 1) {
1171             
foreach ($toArr as $toAddr) {
1172                 $result = $
this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
1173                 $
this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From);
1174             }
1175         }
else {
1176             $result = $
this->mailPassthru($to, $this->Subject, $body, $header, $params);
1177             $
this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From);
1178         }
1179         
if (isset($old_from)) {
1180             ini_set(
'sendmail_from', $old_from);
1181         }
1182         
if (!$result) {
1183             
throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL);
1184         }
1185         
return true;
1186     }
1187
1188     
/**
1189      * Get an instance to use
for SMTP operations.
1190      * Override
this function to load your own SMTP implementation
1191      * @
return SMTP
1192      */

1193     
public function getSMTPInstance()
1194     {
1195         
if (!is_object($this->smtp)) {
1196             $
this->smtp = new SMTP;
1197         }
1198         
return $this->smtp;
1199     }
1200
1201     
/**
1202      * Send mail via SMTP.
1203      * Returns
false if there is a bad MAIL FROM, RCPT, or DATA input.
1204      * Uses the PHPMailerSMTP
class by default.
1205      * @see PHPMailer::getSMTPInstance() to use a different
class.
1206      * @param
string $header The message headers
1207      * @param
string $body The message body
1208      * @throws phpmailerException
1209      * @uses SMTP
1210      * @access
protected
1211      * @
return boolean
1212      */

1213     
protected function smtpSend($header, $body)
1214     {
1215         $bad_rcpt = array();
1216
1217         
if (!$this->smtpConnect()) {
1218             
throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
1219         }
1220         $smtp_from = ($
this->Sender == '') ? $this->From : $this->Sender;
1221         
if (!$this->smtp->mail($smtp_from)) {
1222             $
this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
1223             
throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL);
1224         }
1225
1226         
// Attempt to send to all recipients
1227         
foreach ($this->to as $to) {
1228             
if (!$this->smtp->recipient($to[0])) {
1229                 $bad_rcpt[] = $to[
0];
1230                 $isSent =
false;
1231             }
else {
1232                 $isSent =
true;
1233             }
1234             $
this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From);
1235         }
1236         
foreach ($this->cc as $cc) {
1237             
if (!$this->smtp->recipient($cc[0])) {
1238                 $bad_rcpt[] = $cc[
0];
1239                 $isSent =
false;
1240             }
else {
1241                 $isSent =
true;
1242             }
1243             $
this->doCallback($isSent, array(), array($cc[0]), array(), $this->Subject, $body, $this->From);
1244         }
1245         
foreach ($this->bcc as $bcc) {
1246             
if (!$this->smtp->recipient($bcc[0])) {
1247                 $bad_rcpt[] = $bcc[
0];
1248                 $isSent =
false;
1249             }
else {
1250                 $isSent =
true;
1251             }
1252             $
this->doCallback($isSent, array(), array(), array($bcc[0]), $this->Subject, $body, $this->From);
1253         }
1254
1255         
// Only send the DATA command if we have viable recipients
1256         
if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) {
1257             
throw new phpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL);
1258         }
1259         
if ($this->SMTPKeepAlive) {
1260             $
this->smtp->reset();
1261         }
else {
1262             $
this->smtp->quit();
1263             $
this->smtp->close();
1264         }
1265         
if (count($bad_rcpt) > 0) { // Create error message for any bad addresses
1266             
throw new phpmailerException(
1267                 $
this->lang('recipients_failed') . implode(', ', $bad_rcpt),
1268                 self::STOP_CONTINUE
1269             );
1270         }
1271         
return true;
1272     }
1273
1274     
/**
1275      * Initiate a connection to an SMTP server.
1276      * Returns
false if the operation failed.
1277      * @param array $options An array of options compatible with stream_context_create()
1278      * @uses SMTP
1279      * @access
public
1280      * @throws phpmailerException
1281      * @
return boolean
1282      */

1283     
public function smtpConnect($options = array())
1284     {
1285         
if (is_null($this->smtp)) {
1286             $
this->smtp = $this->getSMTPInstance();
1287         }
1288
1289         
// Already connected?
1290         
if ($this->smtp->connected()) {
1291             
return true;
1292         }
1293
1294         $
this->smtp->setTimeout($this->Timeout);
1295         $
this->smtp->setDebugLevel($this->SMTPDebug);
1296         $
this->smtp->setDebugOutput($this->Debugoutput);
1297         $
this->smtp->setVerp($this->do_verp);
1298         $hosts = explode(
';', $this->Host);
1299         $lastexception =
null;
1300
1301         
foreach ($hosts as $hostentry) {
1302             $hostinfo = array();
1303             
if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) {
1304                 
// Not a valid host entry
1305                 
continue;
1306             }
1307             
// $hostinfo[2]: optional ssl or tls prefix
1308             
// $hostinfo[3]: the hostname
1309             
// $hostinfo[4]: optional port number
1310             
// The host string prefix can temporarily override the current setting for SMTPSecure
1311             
// If it's not specified, the default value is used
1312             $prefix =
'';
1313             $tls = ($
this->SMTPSecure == 'tls');
1314             
if ($hostinfo[2] == 'ssl' or ($hostinfo[2] == '' and $this->SMTPSecure == 'ssl')) {
1315                 $prefix =
'ssl://';
1316                 $tls =
false; // Can't have SSL and TLS at once
1317             } elseif ($hostinfo[
2] == 'tls') {
1318                 $tls =
true;
1319                 
// tls doesn't use a prefix
1320             }
1321             $host = $hostinfo[
3];
1322             $port = $
this->Port;
1323             $tport = (integer)$hostinfo[
4];
1324             
if ($tport > 0 and $tport < 65536) {
1325                 $port = $tport;
1326             }
1327             
if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
1328                 
try {
1329                     
if ($this->Helo) {
1330                         $hello = $
this->Helo;
1331                     }
else {
1332                         $hello = $
this->serverHostname();
1333                     }
1334                     $
this->smtp->hello($hello);
1335
1336                     
if ($tls) {
1337                         
if (!$this->smtp->startTLS()) {
1338                             
throw new phpmailerException($this->lang('connect_host'));
1339                         }
1340                         
// We must resend HELO after tls negotiation
1341                         $
this->smtp->hello($hello);
1342                     }
1343                     
if ($this->SMTPAuth) {
1344                         
if (!$this->smtp->authenticate(
1345                             $
this->Username,
1346                             $
this->Password,
1347                             $
this->AuthType,
1348                             $
this->Realm,
1349                             $
this->Workstation
1350                         )
1351                         ) {
1352                             
throw new phpmailerException($this->lang('authenticate'));
1353                         }
1354                     }
1355                     
return true;
1356                 }
catch (phpmailerException $exc) {
1357                     $lastexception = $exc;
1358                     
// We must have connected, but then failed TLS or Auth, so close connection nicely
1359                     $
this->smtp->quit();
1360                 }
1361             }
1362         }
1363         
// If we get here, all connection attempts have failed, so close connection hard
1364         $
this->smtp->close();
1365         
// As we've caught all exceptions, just report whatever the last one was
1366         
if ($this->exceptions and !is_null($lastexception)) {
1367             
throw $lastexception;
1368         }
1369         
return false;
1370     }
1371
1372     
/**
1373      * Close the active SMTP session
if one exists.
1374      * @
return void
1375      */

1376     
public function smtpClose()
1377     {
1378         
if ($this->smtp !== null) {
1379             
if ($this->smtp->connected()) {
1380                 $
this->smtp->quit();
1381                 $
this->smtp->close();
1382             }
1383         }
1384     }
1385
1386     
/**
1387      * Set the language
for error messages.
1388      * Returns
false if it cannot load the language file.
1389      * The
default language is English.
1390      * @param
string $langcode ISO 639-1 2-character language code (e.g. French is "fr")
1391      * @param
string $lang_path Path to the language file directory, with trailing separator (slash)
1392      * @
return boolean
1393      * @access
public
1394      */

1395     
public function setLanguage($langcode = 'en', $lang_path = '')
1396     {
1397         
// Define full set of translatable strings in English
1398         $PHPMAILER_LANG = array(
1399             
'authenticate' => 'SMTP Error: Could not authenticate.',
1400             
'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
1401             
'data_not_accepted' => 'SMTP Error: data not accepted.',
1402             
'empty_message' => 'Message body empty',
1403             
'encoding' => 'Unknown encoding: ',
1404             
'execute' => 'Could not execute: ',
1405             
'file_access' => 'Could not access file: ',
1406             
'file_open' => 'File Error: Could not open file: ',
1407             
'from_failed' => 'The following From address failed: ',
1408             
'instantiate' => 'Could not instantiate mail function.',
1409             
'invalid_address' => 'Invalid address',
1410             
'mailer_not_supported' => ' mailer is not supported.',
1411             
'provide_address' => 'You must provide at least one recipient email address.',
1412             
'recipients_failed' => 'SMTP Error: The following recipients failed: ',
1413             
'signing' => 'Signing Error: ',
1414             
'smtp_connect_failed' => 'SMTP connect() failed.',
1415             
'smtp_error' => 'SMTP server error: ',
1416             
'variable_set' => 'Cannot set or reset variable: '
1417         );
1418         
if (empty($lang_path)) {
1419             
// Calculate an absolute path so it can work if CWD is not here
1420             $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR .
'language'. DIRECTORY_SEPARATOR;
1421         }
1422         $foundlang =
true;
1423         $lang_file = $lang_path .
'phpmailer.lang-' . $langcode . '.php';
1424         
if ($langcode != 'en') { // There is no English translation file
1425             
// Make sure language file path is readable
1426             
if (!is_readable($lang_file)) {
1427                 $foundlang =
false;
1428             }
else {
1429                 
// Overwrite language-specific strings.
1430                 
// This way we'll never have missing translations.
1431                 $foundlang = include $lang_file;
1432             }
1433         }
1434         $
this->language = $PHPMAILER_LANG;
1435         
return (boolean)$foundlang; // Returns false if language not found
1436     }
1437
1438     
/**
1439      * Get the array of strings
for the current language.
1440      * @
return array
1441      */

1442     
public function getTranslations()
1443     {
1444         
return $this->language;
1445     }
1446
1447     
/**
1448      * Create recipient headers.
1449      * @access
public
1450      * @param
string $type
1451      * @param array $addr An array of recipient,
1452      *
where each recipient is a 2-element indexed array with element 0 containing an address
1453      * and element
1 containing a name, like:
1454      * array(array(
'joe@example.com', 'Joe User'), array('zoe@example.com', 'Zoe User'))
1455      * @
return string
1456      */

1457     
public function addrAppend($type, $addr)
1458     {
1459         $addresses = array();
1460         
foreach ($addr as $address) {
1461             $addresses[] = $
this->addrFormat($address);
1462         }
1463         
return $type . ': ' . implode(', ', $addresses) . $this->LE;
1464     }
1465
1466     
/**
1467      * Format an address
for use in a message header.
1468      * @access
public
1469      * @param array $addr A
2-element indexed array, element 0 containing an address, element 1 containing a name
1470      * like array(
'joe@example.com', 'Joe User')
1471      * @
return string
1472      */

1473     
public function addrFormat($addr)
1474     {
1475         
if (empty($addr[1])) { // No name provided
1476             
return $this->secureHeader($addr[0]);
1477         }
else {
1478             
return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader(
1479                 $addr[
0]
1480             ) .
'>';
1481         }
1482     }
1483
1484     
/**
1485      * Word-wrap message.
1486      * For use with mailers that
do not automatically perform wrapping
1487      * and
for quoted-printable encoded messages.
1488      * Original written
by philippe.
1489      * @param
string $message The message to wrap
1490      * @param integer $length The line length to wrap to
1491      * @param boolean $qp_mode Whether to run
in Quoted-Printable mode
1492      * @access
public
1493      * @
return string
1494      */

1495     
public function wrapText($message, $length, $qp_mode = false)
1496     {
1497         $soft_break = ($qp_mode) ? sprintf(
' =%s', $this->LE) : $this->LE;
1498         
// If utf-8 encoding is used, we will need to make sure we don't
1499         
// split multibyte characters when we wrap
1500         $is_utf8 = (strtolower($
this->CharSet) == 'utf-8');
1501         $lelen = strlen($
this->LE);
1502         $crlflen = strlen(self::CRLF);
1503
1504         $message = $
this->fixEOL($message);
1505         
if (substr($message, -$lelen) == $this->LE) {
1506             $message = substr($message,
0, -$lelen);
1507         }
1508
1509         $line = explode($
this->LE, $message); // Magic. We know fixEOL uses $LE
1510         $message =
'';
1511         
for ($i = 0; $i < count($line); $i++) {
1512             $line_part = explode(
' ', $line[$i]);
1513             $buf =
'';
1514             
for ($e = 0; $e < count($line_part); $e++) {
1515                 $word = $line_part[$e];
1516                 
if ($qp_mode and (strlen($word) > $length)) {
1517                     $space_left = $length - strlen($buf) - $crlflen;
1518                     
if ($e != 0) {
1519                         
if ($space_left > 20) {
1520                             $len = $space_left;
1521                             
if ($is_utf8) {
1522                                 $len = $
this->utf8CharBoundary($word, $len);
1523                             } elseif (substr($word, $len -
1, 1) == '=') {
1524                                 $len--;
1525                             } elseif (substr($word, $len -
2, 1) == '=') {
1526                                 $len -=
2;
1527                             }
1528                             $part = substr($word,
0, $len);
1529                             $word = substr($word, $len);
1530                             $buf .=
' ' . $part;
1531                             $message .= $buf . sprintf(
'=%s', self::CRLF);
1532                         }
else {
1533                             $message .= $buf . $soft_break;
1534                         }
1535                         $buf =
'';
1536                     }
1537                     
while (strlen($word) > 0) {
1538                         
if ($length <= 0) {
1539                             
break;
1540                         }
1541                         $len = $length;
1542                         
if ($is_utf8) {
1543                             $len = $
this->utf8CharBoundary($word, $len);
1544                         } elseif (substr($word, $len -
1, 1) == '=') {
1545                             $len--;
1546                         } elseif (substr($word, $len -
2, 1) == '=') {
1547                             $len -=
2;
1548                         }
1549                         $part = substr($word,
0, $len);
1550                         $word = substr($word, $len);
1551
1552                         
if (strlen($word) > 0) {
1553                             $message .= $part . sprintf(
'=%s', self::CRLF);
1554                         }
else {
1555                             $buf = $part;
1556                         }
1557                     }
1558                 }
else {
1559                     $buf_o = $buf;
1560                     $buf .= ($e ==
0) ? $word : (' ' . $word);
1561
1562                     
if (strlen($buf) > $length and $buf_o != '') {
1563                         $message .= $buf_o . $soft_break;
1564                         $buf = $word;
1565                     }
1566                 }
1567             }
1568             $message .= $buf . self::CRLF;
1569         }
1570
1571         
return $message;
1572     }
1573
1574     
/**
1575      * Find the last character boundary prior to $maxLength
in a utf-8
1576      * quoted (printable) encoded
string.
1577      * Original written
by Colin Brown.
1578      * @access
public
1579      * @param
string $encodedText utf-8 QP text
1580      * @param integer $maxLength find last character boundary prior to
this length
1581      * @
return integer
1582      */

1583     
public function utf8CharBoundary($encodedText, $maxLength)
1584     {
1585         $foundSplitPos =
false;
1586         $lookBack =
3;
1587         
while (!$foundSplitPos) {
1588             $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
1589             $encodedCharPos = strpos($lastChunk,
'=');
1590             
if (false !== $encodedCharPos) {
1591                 
// Found start of encoded character byte within $lookBack block.
1592                 
// Check the encoded byte value (the 2 chars after the '=')
1593                 $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos +
1, 2);
1594                 $dec = hexdec($hex);
1595                 
if ($dec < 128) { // Single byte character.
1596                     
// If the encoded char was found at pos 0, it will fit
1597                     
// otherwise reduce maxLength to start of the encoded char
1598                     $maxLength = ($encodedCharPos ==
0) ? $maxLength :
1599                         $maxLength - ($lookBack - $encodedCharPos);
1600                     $foundSplitPos =
true;
1601                 } elseif ($dec >=
192) { // First byte of a multi byte character
1602                     
// Reduce maxLength to split at start of character
1603                     $maxLength = $maxLength - ($lookBack - $encodedCharPos);
1604                     $foundSplitPos =
true;
1605                 } elseif ($dec <
192) { // Middle byte of a multi byte character, look further back
1606                     $lookBack +=
3;
1607                 }
1608             }
else {
1609                 
// No encoded character found
1610                 $foundSplitPos =
true;
1611             }
1612         }
1613         
return $maxLength;
1614     }
1615
1616     
/**
1617      * Set the body wrapping.
1618      * @access
public
1619      * @
return void
1620      */

1621     
public function setWordWrap()
1622     {
1623         
if ($this->WordWrap < 1) {
1624             
return;
1625         }
1626
1627         
switch ($this->message_type) {
1628             
case 'alt':
1629             
case 'alt_inline':
1630             
case 'alt_attach':
1631             
case 'alt_inline_attach':
1632                 $
this->AltBody = $this->wrapText($this->AltBody, $this->WordWrap);
1633                 
break;
1634             
default:
1635                 $
this->Body = $this->wrapText($this->Body, $this->WordWrap);
1636                 
break;
1637         }
1638     }
1639
1640     
/**
1641      * Assemble message headers.
1642      * @access
public
1643      * @
return string The assembled headers
1644      */

1645     
public function createHeader()
1646     {
1647         $result =
'';
1648
1649         
// Set the boundaries
1650         $uniq_id = md5(uniqid(time()));
1651         $
this->boundary[1] = 'b1_' . $uniq_id;
1652         $
this->boundary[2] = 'b2_' . $uniq_id;
1653         $
this->boundary[3] = 'b3_' . $uniq_id;
1654
1655         
if ($this->MessageDate == '') {
1656             $
this->MessageDate = self::rfcDate();
1657         }
1658         $result .= $
this->headerLine('Date', $this->MessageDate);
1659
1660
1661         
// To be created automatically by mail()
1662         
if ($this->SingleTo) {
1663             
if ($this->Mailer != 'mail') {
1664                 
foreach ($this->to as $toaddr) {
1665                     $
this->SingleToArray[] = $this->addrFormat($toaddr);
1666                 }
1667             }
1668         }
else {
1669             
if (count($this->to) > 0) {
1670                 
if ($this->Mailer != 'mail') {
1671                     $result .= $
this->addrAppend('To', $this->to);
1672                 }
1673             } elseif (count($
this->cc) == 0) {
1674                 $result .= $
this->headerLine('To', 'undisclosed-recipients:;');
1675             }
1676         }
1677
1678         $result .= $
this->addrAppend('From', array(array(trim($this->From), $this->FromName)));
1679
1680         
// sendmail and mail() extract Cc from the header before sending
1681         
if (count($this->cc) > 0) {
1682             $result .= $
this->addrAppend('Cc', $this->cc);
1683         }
1684
1685         
// sendmail and mail() extract Bcc from the header before sending
1686         
if ((
1687                 $
this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail'
1688             )
1689             and count($
this->bcc) > 0
1690         ) {
1691             $result .= $
this->addrAppend('Bcc', $this->bcc);
1692         }
1693
1694         
if (count($this->ReplyTo) > 0) {
1695             $result .= $
this->addrAppend('Reply-To', $this->ReplyTo);
1696         }
1697
1698         
// mail() sets the subject itself
1699         
if ($this->Mailer != 'mail') {
1700             $result .= $
this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
1701         }
1702
1703         
if ($this->MessageID != '') {
1704             $
this->lastMessageID = $this->MessageID;
1705         }
else {
1706             $
this->lastMessageID = sprintf('<%s@%s>', $uniq_id, $this->ServerHostname());
1707         }
1708         $result .= $
this->HeaderLine('Message-ID', $this->lastMessageID);
1709         $result .= $
this->headerLine('X-Priority', $this->Priority);
1710         
if ($this->XMailer == '') {
1711             $result .= $
this->headerLine(
1712                 
'X-Mailer',
1713                 
'PHPMailer ' . $this->Version . ' (https://github.com/PHPMailer/PHPMailer/)'
1714             );
1715         }
else {
1716             $myXmailer = trim($
this->XMailer);
1717             
if ($myXmailer) {
1718                 $result .= $
this->headerLine('X-Mailer', $myXmailer);
1719             }
1720         }
1721
1722         
if ($this->ConfirmReadingTo != '') {
1723             $result .= $
this->headerLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
1724         }
1725
1726         
// Add custom headers
1727         
for ($index = 0; $index < count($this->CustomHeader); $index++) {
1728             $result .= $
this->headerLine(
1729                 trim($
this->CustomHeader[$index][0]),
1730                 $
this->encodeHeader(trim($this->CustomHeader[$index][1]))
1731             );
1732         }
1733         
if (!$this->sign_key_file) {
1734             $result .= $
this->headerLine('MIME-Version', '1.0');
1735             $result .= $
this->getMailMIME();
1736         }
1737
1738         
return $result;
1739     }
1740
1741     
/**
1742      * Get the message MIME type headers.
1743      * @access
public
1744      * @
return string
1745      */

1746     
public function getMailMIME()
1747     {
1748         $result =
'';
1749         $ismultipart =
true;
1750         
switch ($this->message_type) {
1751             
case 'inline':
1752                 $result .= $
this->headerLine('Content-Type', 'multipart/related;');
1753                 $result .= $
this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
1754                 
break;
1755             
case 'attach':
1756             
case 'inline_attach':
1757             
case 'alt_attach':
1758             
case 'alt_inline_attach':
1759                 $result .= $
this->headerLine('Content-Type', 'multipart/mixed;');
1760                 $result .= $
this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
1761                 
break;
1762             
case 'alt':
1763             
case 'alt_inline':
1764                 $result .= $
this->headerLine('Content-Type', 'multipart/alternative;');
1765                 $result .= $
this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
1766                 
break;
1767             
default:
1768                 
// Catches case 'plain': and case '':
1769                 $result .= $
this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet);
1770                 $ismultipart =
false;
1771                 
break;
1772         }
1773         
// RFC1341 part 5 says 7bit is assumed if not specified
1774         
if ($this->Encoding != '7bit') {
1775             
// RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
1776             
if ($ismultipart) {
1777                 
if ($this->Encoding == '8bit') {
1778                     $result .= $
this->headerLine('Content-Transfer-Encoding', '8bit');
1779                 }
1780                 
// The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
1781             }
else {
1782                 $result .= $
this->headerLine('Content-Transfer-Encoding', $this->Encoding);
1783             }
1784         }
1785
1786         
if ($this->Mailer != 'mail') {
1787             $result .= $
this->LE;
1788         }
1789
1790         
return $result;
1791     }
1792
1793     
/**
1794      * Returns the whole MIME message.
1795      * Includes complete headers and body.
1796      * Only valid post preSend().
1797      * @see PHPMailer::preSend()
1798      * @access
public
1799      * @
return string
1800      */

1801     
public function getSentMIMEMessage()
1802     {
1803         
return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody;
1804     }
1805
1806
1807     
/**
1808      * Assemble the message body.
1809      * Returns an empty
string on failure.
1810      * @access
public
1811      * @throws phpmailerException
1812      * @
return string The assembled message body
1813      */

1814     
public function createBody()
1815     {
1816         $body =
'';
1817
1818         
if ($this->sign_key_file) {
1819             $body .= $
this->getMailMIME() . $this->LE;
1820         }
1821
1822         $
this->setWordWrap();
1823
1824         $bodyEncoding = $
this->Encoding;
1825         $bodyCharSet = $
this->CharSet;
1826         
if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) {
1827             $bodyEncoding =
'7bit';
1828             $bodyCharSet =
'us-ascii';
1829         }
1830         $altBodyEncoding = $
this->Encoding;
1831         $altBodyCharSet = $
this->CharSet;
1832         
if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) {
1833             $altBodyEncoding =
'7bit';
1834             $altBodyCharSet =
'us-ascii';
1835         }
1836         
switch ($this->message_type) {
1837             
case 'inline':
1838                 $body .= $
this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
1839                 $body .= $
this->encodeString($this->Body, $bodyEncoding);
1840                 $body .= $
this->LE . $this->LE;
1841                 $body .= $
this->attachAll('inline', $this->boundary[1]);
1842                 
break;
1843             
case 'attach':
1844                 $body .= $
this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
1845                 $body .= $
this->encodeString($this->Body, $bodyEncoding);
1846                 $body .= $
this->LE . $this->LE;
1847                 $body .= $
this->attachAll('attachment', $this->boundary[1]);
1848                 
break;
1849             
case 'inline_attach':
1850                 $body .= $
this->textLine('--' . $this->boundary[1]);
1851                 $body .= $
this->headerLine('Content-Type', 'multipart/related;');
1852                 $body .= $
this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
1853                 $body .= $
this->LE;
1854                 $body .= $
this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding);
1855                 $body .= $
this->encodeString($this->Body, $bodyEncoding);
1856                 $body .= $
this->LE . $this->LE;
1857                 $body .= $
this->attachAll('inline', $this->boundary[2]);
1858                 $body .= $
this->LE;
1859                 $body .= $
this->attachAll('attachment', $this->boundary[1]);
1860                 
break;
1861             
case 'alt':
1862                 $body .= $
this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
1863                 $body .= $
this->encodeString($this->AltBody, $altBodyEncoding);
1864                 $body .= $
this->LE . $this->LE;
1865                 $body .= $
this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding);
1866                 $body .= $
this->encodeString($this->Body, $bodyEncoding);
1867                 $body .= $
this->LE . $this->LE;
1868                 
if (!empty($this->Ical)) {
1869                     $body .= $
this->getBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', '');
1870                     $body .= $
this->encodeString($this->Ical, $this->Encoding);
1871                     $body .= $
this->LE . $this->LE;
1872                 }
1873                 $body .= $
this->endBoundary($this->boundary[1]);
1874                 
break;
1875             
case 'alt_inline':
1876                 $body .= $
this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
1877                 $body .= $
this->encodeString($this->AltBody, $altBodyEncoding);
1878                 $body .= $
this->LE . $this->LE;
1879                 $body .= $
this->textLine('--' . $this->boundary[1]);
1880                 $body .= $
this->headerLine('Content-Type', 'multipart/related;');
1881                 $body .= $
this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
1882                 $body .= $
this->LE;
1883                 $body .= $
this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
1884                 $body .= $
this->encodeString($this->Body, $bodyEncoding);
1885                 $body .= $
this->LE . $this->LE;
1886                 $body .= $
this->attachAll('inline', $this->boundary[2]);
1887                 $body .= $
this->LE;
1888                 $body .= $
this->endBoundary($this->boundary[1]);
1889                 
break;
1890             
case 'alt_attach':
1891                 $body .= $
this->textLine('--' . $this->boundary[1]);
1892                 $body .= $
this->headerLine('Content-Type', 'multipart/alternative;');
1893                 $body .= $
this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
1894                 $body .= $
this->LE;
1895                 $body .= $
this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
1896                 $body .= $
this->encodeString($this->AltBody, $altBodyEncoding);
1897                 $body .= $
this->LE . $this->LE;
1898                 $body .= $
this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
1899                 $body .= $
this->encodeString($this->Body, $bodyEncoding);
1900                 $body .= $
this->LE . $this->LE;
1901                 $body .= $
this->endBoundary($this->boundary[2]);
1902                 $body .= $
this->LE;
1903                 $body .= $
this->attachAll('attachment', $this->boundary[1]);
1904                 
break;
1905             
case 'alt_inline_attach':
1906                 $body .= $
this->textLine('--' . $this->boundary[1]);
1907                 $body .= $
this->headerLine('Content-Type', 'multipart/alternative;');
1908                 $body .= $
this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
1909                 $body .= $
this->LE;
1910                 $body .= $
this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
1911                 $body .= $
this->encodeString($this->AltBody, $altBodyEncoding);
1912                 $body .= $
this->LE . $this->LE;
1913                 $body .= $
this->textLine('--' . $this->boundary[2]);
1914                 $body .= $
this->headerLine('Content-Type', 'multipart/related;');
1915                 $body .= $
this->textLine("\tboundary=\"" . $this->boundary[3] . '"');
1916                 $body .= $
this->LE;
1917                 $body .= $
this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding);
1918                 $body .= $
this->encodeString($this->Body, $bodyEncoding);
1919                 $body .= $
this->LE . $this->LE;
1920                 $body .= $
this->attachAll('inline', $this->boundary[3]);
1921                 $body .= $
this->LE;
1922                 $body .= $
this->endBoundary($this->boundary[2]);
1923                 $body .= $
this->LE;
1924                 $body .= $
this->attachAll('attachment', $this->boundary[1]);
1925                 
break;
1926             
default:
1927                 
// catch case 'plain' and case ''
1928                 $body .= $
this->encodeString($this->Body, $bodyEncoding);
1929                 
break;
1930         }
1931
1932         
if ($this->isError()) {
1933             $body =
'';
1934         } elseif ($
this->sign_key_file) {
1935             
try {
1936                 
if (!defined('PKCS7_TEXT')) {
1937                     
throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.');
1938                 }
1939                 
// @TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1
1940                 $file = tempnam(sys_get_temp_dir(),
'mail');
1941                 
if (false === file_put_contents($file, $body)) {
1942                     
throw new phpmailerException($this->lang('signing') . ' Could not write temp file');
1943                 }
1944                 $signed = tempnam(sys_get_temp_dir(),
'signed');
1945                 
if (@openssl_pkcs7_sign(
1946                     $file,
1947                     $signed,
1948                     
'file://' . realpath($this->sign_cert_file),
1949                     array(
'file://' . realpath($this->sign_key_file), $this->sign_key_pass),
1950                     
null
1951                 )
1952                 ) {
1953                     @unlink($file);
1954                     $body = file_get_contents($signed);
1955                     @unlink($signed);
1956                 }
else {
1957                     @unlink($file);
1958                     @unlink($signed);
1959                     
throw new phpmailerException($this->lang('signing') . openssl_error_string());
1960                 }
1961             }
catch (phpmailerException $exc) {
1962                 $body =
'';
1963                 
if ($this->exceptions) {
1964                     
throw $exc;
1965                 }
1966             }
1967         }
1968         
return $body;
1969     }
1970
1971     
/**
1972      * Return the start of a message boundary.
1973      * @access
protected
1974      * @param
string $boundary
1975      * @param
string $charSet
1976      * @param
string $contentType
1977      * @param
string $encoding
1978      * @
return string
1979      */

1980     
protected function getBoundary($boundary, $charSet, $contentType, $encoding)
1981     {
1982         $result =
'';
1983         
if ($charSet == '') {
1984             $charSet = $
this->CharSet;
1985         }
1986         
if ($contentType == '') {
1987             $contentType = $
this->ContentType;
1988         }
1989         
if ($encoding == '') {
1990             $encoding = $
this->Encoding;
1991         }
1992         $result .= $
this->textLine('--' . $boundary);
1993         $result .= sprintf(
'Content-Type: %s; charset=%s', $contentType, $charSet);
1994         $result .= $
this->LE;
1995         
// RFC1341 part 5 says 7bit is assumed if not specified
1996         
if ($encoding != '7bit') {
1997             $result .= $
this->headerLine('Content-Transfer-Encoding', $encoding);
1998         }
1999         $result .= $
this->LE;
2000
2001         
return $result;
2002     }
2003
2004     
/**
2005      * Return the end of a message boundary.
2006      * @access
protected
2007      * @param
string $boundary
2008      * @
return string
2009      */

2010     
protected function endBoundary($boundary)
2011     {
2012         
return $this->LE . '--' . $boundary . '--' . $this->LE;
2013     }
2014
2015     
/**
2016      * Set the message type.
2017      * PHPMailer only supports some preset message types,
2018      * not arbitrary MIME structures.
2019      * @access
protected
2020      * @
return void
2021      */

2022     
protected function setMessageType()
2023     {
2024         $type = array();
2025         
if ($this->alternativeExists()) {
2026             $type[] =
'alt';
2027         }
2028         
if ($this->inlineImageExists()) {
2029             $type[] =
'inline';
2030         }
2031         
if ($this->attachmentExists()) {
2032             $type[] =
'attach';
2033         }
2034         $
this->message_type = implode('_', $type);
2035         
if ($this->message_type == '') {
2036             $
this->message_type = 'plain';
2037         }
2038     }
2039
2040     
/**
2041      * Format a header line.
2042      * @access
public
2043      * @param
string $name
2044      * @param
string $value
2045      * @
return string
2046      */

2047     
public function headerLine($name, $value)
2048     {
2049         
return $name . ': ' . $value . $this->LE;
2050     }
2051
2052     
/**
2053      * Return a formatted mail line.
2054      * @access
public
2055      * @param
string $value
2056      * @
return string
2057      */

2058     
public function textLine($value)
2059     {
2060         
return $value . $this->LE;
2061     }
2062
2063     
/**
2064      * Add an attachment
from a path on the filesystem.
2065      * Returns
false if the file could not be found or read.
2066      * @param
string $path Path to the attachment.
2067      * @param
string $name Overrides the attachment name.
2068      * @param
string $encoding File encoding (see $Encoding).
2069      * @param
string $type File extension (MIME) type.
2070      * @param
string $disposition Disposition to use
2071      * @throws phpmailerException
2072      * @
return boolean
2073      */

2074     
public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment')
2075     {
2076         
try {
2077             
if (!@is_file($path)) {
2078                 
throw new phpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE);
2079             }
2080
2081             
// If a MIME type is not specified, try to work it out from the file name
2082             
if ($type == '') {
2083                 $type = self::filenameToType($path);
2084             }
2085
2086             $filename = basename($path);
2087             
if ($name == '') {
2088                 $name = $filename;
2089             }
2090
2091             $
this->attachment[] = array(
2092                 
0 => $path,
2093                 
1 => $filename,
2094                 
2 => $name,
2095                 
3 => $encoding,
2096                 
4 => $type,
2097                 
5 => false, // isStringAttachment
2098                 
6 => $disposition,
2099                 
7 => 0
2100             );
2101
2102         }
catch (phpmailerException $exc) {
2103             $
this->setError($exc->getMessage());
2104             $
this->edebug($exc->getMessage());
2105             
if ($this->exceptions) {
2106                 
throw $exc;
2107             }
2108             
return false;
2109         }
2110         
return true;
2111     }
2112
2113     
/**
2114      * Return the array of attachments.
2115      * @
return array
2116      */

2117     
public function getAttachments()
2118     {
2119         
return $this->attachment;
2120     }
2121
2122     
/**
2123      * Attach all file,
string, and binary attachments to the message.
2124      * Returns an empty
string on failure.
2125      * @access
protected
2126      * @param
string $disposition_type
2127      * @param
string $boundary
2128      * @
return string
2129      */

2130     
protected function attachAll($disposition_type, $boundary)
2131     {
2132         
// Return text of body
2133         $mime = array();
2134         $cidUniq = array();
2135         $incl = array();
2136
2137         
// Add all attachments
2138         
foreach ($this->attachment as $attachment) {
2139             
// Check if it is a valid disposition_filter
2140             
if ($attachment[6] == $disposition_type) {
2141                 
// Check for string attachment
2142                 $
string = '';
2143                 $path =
'';
2144                 $bString = $attachment[
5];
2145                 
if ($bString) {
2146                     $
string = $attachment[0];
2147                 }
else {
2148                     $path = $attachment[
0];
2149                 }
2150
2151                 $inclhash = md5(serialize($attachment));
2152                 
if (in_array($inclhash, $incl)) {
2153                     
continue;
2154                 }
2155                 $incl[] = $inclhash;
2156                 $name = $attachment[
2];
2157                 $encoding = $attachment[
3];
2158                 $type = $attachment[
4];
2159                 $disposition = $attachment[
6];
2160                 $cid = $attachment[
7];
2161                 
if ($disposition == 'inline' && isset($cidUniq[$cid])) {
2162                     
continue;
2163                 }
2164                 $cidUniq[$cid] =
true;
2165
2166                 $mime[] = sprintf(
'--%s%s', $boundary, $this->LE);
2167                 $mime[] = sprintf(
2168                     
'Content-Type: %s; name="%s"%s',
2169                     $type,
2170                     $
this->encodeHeader($this->secureHeader($name)),
2171                     $
this->LE
2172                 );
2173                 
// RFC1341 part 5 says 7bit is assumed if not specified
2174                 
if ($encoding != '7bit') {
2175                     $mime[] = sprintf(
'Content-Transfer-Encoding: %s%s', $encoding, $this->LE);
2176                 }
2177
2178                 
if ($disposition == 'inline') {
2179                     $mime[] = sprintf(
'Content-ID: <%s>%s', $cid, $this->LE);
2180                 }
2181
2182                 
// If a filename contains any of these chars, it should be quoted,
2183                 
// but not otherwise: RFC2183 & RFC2045 5.1
2184                 
// Fixes a warning in IETF's msglint MIME checker
2185                 
// Allow for bypassing the Content-Disposition header totally
2186                 
if (!(empty($disposition))) {
2187                     $encoded_name = $
this->encodeHeader($this->secureHeader($name));
2188                     
if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $encoded_name)) {
2189                         $mime[] = sprintf(
2190                             
'Content-Disposition: %s; filename="%s"%s',
2191                             $disposition,
2192                             $encoded_name,
2193                             $
this->LE . $this->LE
2194                         );
2195                     }
else {
2196                         $mime[] = sprintf(
2197                             
'Content-Disposition: %s; filename=%s%s',
2198                             $disposition,
2199                             $encoded_name,
2200                             $
this->LE . $this->LE
2201                         );
2202                     }
2203                 }
else {
2204                     $mime[] = $
this->LE;
2205                 }
2206
2207                 
// Encode as string attachment
2208                 
if ($bString) {
2209                     $mime[] = $
this->encodeString($string, $encoding);
2210                     
if ($this->isError()) {
2211                         
return '';
2212                     }
2213                     $mime[] = $
this->LE . $this->LE;
2214                 }
else {
2215                     $mime[] = $
this->encodeFile($path, $encoding);
2216                     
if ($this->isError()) {
2217                         
return '';
2218                     }
2219                     $mime[] = $
this->LE . $this->LE;
2220                 }
2221             }
2222         }
2223
2224         $mime[] = sprintf(
'--%s--%s', $boundary, $this->LE);
2225
2226         
return implode('', $mime);
2227     }
2228
2229     
/**
2230      * Encode a file attachment
in requested format.
2231      * Returns an empty
string on failure.
2232      * @param
string $path The full path to the file
2233      * @param
string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
2234      * @throws phpmailerException
2235      * @see EncodeFile(encodeFile
2236      * @access
protected
2237      * @
return string
2238      */

2239     
protected function encodeFile($path, $encoding = 'base64')
2240     {
2241         
try {
2242             
if (!is_readable($path)) {
2243                 
throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE);
2244             }
2245             $magic_quotes = get_magic_quotes_runtime();
2246             
if ($magic_quotes) {
2247                 
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
2248                     set_magic_quotes_runtime(
false);
2249                 }
else {
2250                     
//Doesn't exist in PHP 5.4, but we don't need to check because
2251                     
//get_magic_quotes_runtime always returns false in 5.4+
2252                     
//so it will never get here
2253                     ini_set(
'magic_quotes_runtime', 0);
2254                 }
2255             }
2256             $file_buffer = file_get_contents($path);
2257             $file_buffer = $
this->encodeString($file_buffer, $encoding);
2258             
if ($magic_quotes) {
2259                 
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
2260                     set_magic_quotes_runtime($magic_quotes);
2261                 }
else {
2262                     ini_set(
'magic_quotes_runtime', ($magic_quotes?'1':'0'));
2263                 }
2264             }
2265             
return $file_buffer;
2266         }
catch (Exception $exc) {
2267             $
this->setError($exc->getMessage());
2268             
return '';
2269         }
2270     }
2271
2272     
/**
2273      * Encode a
string in requested format.
2274      * Returns an empty
string on failure.
2275      * @param
string $str The text to encode
2276      * @param
string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
2277      * @access
public
2278      * @
return string
2279      */

2280     
public function encodeString($str, $encoding = 'base64')
2281     {
2282         $encoded =
'';
2283         
switch (strtolower($encoding)) {
2284             
case 'base64':
2285                 $encoded = chunk_split(base64_encode($str),
76, $this->LE);
2286                 
break;
2287             
case '7bit':
2288             
case '8bit':
2289                 $encoded = $
this->fixEOL($str);
2290                 
// Make sure it ends with a line break
2291                 
if (substr($encoded, -(strlen($this->LE))) != $this->LE) {
2292                     $encoded .= $
this->LE;
2293                 }
2294                 
break;
2295             
case 'binary':
2296                 $encoded = $str;
2297                 
break;
2298             
case 'quoted-printable':
2299                 $encoded = $
this->encodeQP($str);
2300                 
break;
2301             
default:
2302                 $
this->setError($this->lang('encoding') . $encoding);
2303                 
break;
2304         }
2305         
return $encoded;
2306     }
2307
2308     
/**
2309      * Encode a header
string optimally.
2310      * Picks shortest of Q, B, quoted-printable or none.
2311      * @access
public
2312      * @param
string $str
2313      * @param
string $position
2314      * @
return string
2315      */

2316     
public function encodeHeader($str, $position = 'text')
2317     {
2318         $matchcount =
0;
2319         
switch (strtolower($position)) {
2320             
case 'phrase':
2321                 
if (!preg_match('/[\200-\377]/', $str)) {
2322                     
// Can't use addslashes as we don't know the value of magic_quotes_sybase
2323                     $encoded = addcslashes($str,
"\0..\37\177\\\"");
2324                     
if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
2325                         
return ($encoded);
2326                     }
else {
2327                         
return ("\"$encoded\"");
2328                     }
2329                 }
2330                 $matchcount = preg_match_all(
'/[^\040\041\043-\133\135-\176]/', $str, $matches);
2331                 
break;
2332             
/** @noinspection PhpMissingBreakStatementInspection */
2333             
case 'comment':
2334                 $matchcount = preg_match_all(
'/[()"]/', $str, $matches);
2335                 
// Intentional fall-through
2336             
case 'text':
2337             
default:
2338                 $matchcount += preg_match_all(
'/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
2339                 
break;
2340         }
2341
2342         
if ($matchcount == 0) { // There are no chars that need encoding
2343             
return ($str);
2344         }
2345
2346         $maxlen =
75 - 7 - strlen($this->CharSet);
2347         
// Try to select the encoding which should produce the shortest output
2348         
if ($matchcount > strlen($str) / 3) {
2349             
// More than a third of the content will need encoding, so B encoding will be most efficient
2350             $encoding =
'B';
2351             
if (function_exists('mb_strlen') && $this->hasMultiBytes($str)) {
2352                 
// Use a custom function which correctly encodes and wraps long
2353                 
// multibyte strings without breaking lines within a character
2354                 $encoded = $
this->base64EncodeWrapMB($str, "\n");
2355             }
else {
2356                 $encoded = base64_encode($str);
2357                 $maxlen -= $maxlen %
4;
2358                 $encoded = trim(chunk_split($encoded, $maxlen,
"\n"));
2359             }
2360         }
else {
2361             $encoding =
'Q';
2362             $encoded = $
this->encodeQ($str, $position);
2363             $encoded = $
this->wrapText($encoded, $maxlen, true);
2364             $encoded = str_replace(
'=' . self::CRLF, "\n", trim($encoded));
2365         }
2366
2367         $encoded = preg_replace(
'/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded);
2368         $encoded = trim(str_replace(
"\n", $this->LE, $encoded));
2369
2370         
return $encoded;
2371     }
2372
2373     
/**
2374      * Check
if a string contains multi-byte characters.
2375      * @access
public
2376      * @param
string $str multi-byte text to wrap encode
2377      * @
return boolean
2378      */

2379     
public function hasMultiBytes($str)
2380     {
2381         
if (function_exists('mb_strlen')) {
2382             
return (strlen($str) > mb_strlen($str, $this->CharSet));
2383         }
else { // Assume no multibytes (we can't handle without mbstring functions anyway)
2384             
return false;
2385         }
2386     }
2387
2388     
/**
2389      * Does a
string contain any 8-bit chars (in any charset)?
2390      * @param
string $text
2391      * @
return boolean
2392      */

2393     
public function has8bitChars($text)
2394     {
2395         
return (boolean)preg_match('/[\x80-\xFF]/', $text);
2396     }
2397
2398     
/**
2399      * Encode and wrap
long multibyte strings for mail headers
2400      * without breaking lines within a character.
2401      * Adapted
from a function by paravoid
2402      * @link http://www.php.net/manual/en/function.mb-encode-mimeheader.php#
60283
2403      * @access
public
2404      * @param
string $str multi-byte text to wrap encode
2405      * @param
string $linebreak string to use as linefeed/end-of-line
2406      * @
return string
2407      */

2408     
public function base64EncodeWrapMB($str, $linebreak = null)
2409     {
2410         $start =
'=?' . $this->CharSet . '?B?';
2411         $end =
'?=';
2412         $encoded =
'';
2413         
if ($linebreak === null) {
2414             $linebreak = $
this->LE;
2415         }
2416
2417         $mb_length = mb_strlen($str, $
this->CharSet);
2418         
// Each line must have length <= 75, including $start and $end
2419         $length =
75 - strlen($start) - strlen($end);
2420         
// Average multi-byte ratio
2421         $ratio = $mb_length / strlen($str);
2422         
// Base64 has a 4:3 ratio
2423         $avgLength = floor($length * $ratio * .
75);
2424
2425         
for ($i = 0; $i < $mb_length; $i += $offset) {
2426             $lookBack =
0;
2427             
do {
2428                 $offset = $avgLength - $lookBack;
2429                 $chunk = mb_substr($str, $i, $offset, $
this->CharSet);
2430                 $chunk = base64_encode($chunk);
2431                 $lookBack++;
2432             }
while (strlen($chunk) > $length);
2433             $encoded .= $chunk . $linebreak;
2434         }
2435
2436         
// Chomp the last linefeed
2437         $encoded = substr($encoded,
0, -strlen($linebreak));
2438         
return $encoded;
2439     }
2440
2441     
/**
2442      * Encode a
string in quoted-printable format.
2443      * According to RFC2045 section
6.7.
2444      * @access
public
2445      * @param
string $string The text to encode
2446      * @param integer $line_max Number of chars allowed
on a line before wrapping
2447      * @
return string
2448      * @link http://www.php.net/manual/en/function.quoted-printable-decode.php#
89417 Adapted from this comment
2449      */

2450     
public function encodeQP($string, $line_max = 76)
2451     {
2452         
if (function_exists('quoted_printable_encode')) { // Use native function if it's available (>= PHP5.3)
2453             
return $this->fixEOL(quoted_printable_encode($string));
2454         }
2455         
// Fall back to a pure PHP implementation
2456         $
string = str_replace(
2457             array(
'%20', '%0D%0A.', '%0D%0A', '%'),
2458             array(
' ', "\r\n=2E", "\r\n", '='),
2459             rawurlencode($
string)
2460         );
2461         $
string = preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string);
2462         
return $this->fixEOL($string);
2463     }
2464
2465     
/**
2466      * Backward compatibility wrapper
for an old QP encoding function that was removed.
2467      * @see PHPMailer::encodeQP()
2468      * @access
public
2469      * @param
string $string
2470      * @param integer $line_max
2471      * @param boolean $space_conv
2472      * @
return string
2473      * @deprecated Use encodeQP instead.
2474      */

2475     
public function encodeQPphp(
2476         $
string,
2477         $line_max =
76,
2478         
/** @noinspection PhpUnusedParameterInspection */ $space_conv = false
2479     ) {
2480         
return $this->encodeQP($string, $line_max);
2481     }
2482
2483     
/**
2484      * Encode a
string using Q encoding.
2485      * @link http://tools.ietf.org/html/rfc2047
2486      * @param
string $str the text to encode
2487      * @param
string $position Where the text is going to be used, see the RFC for what that means
2488      * @access
public
2489      * @
return string
2490      */

2491     
public function encodeQ($str, $position = 'text')
2492     {
2493         
// There should not be any EOL in the string
2494         $pattern =
'';
2495         $encoded = str_replace(array(
"\r", "\n"), '', $str);
2496         
switch (strtolower($position)) {
2497             
case 'phrase':
2498                 
// RFC 2047 section 5.3
2499                 $pattern =
'^A-Za-z0-9!*+\/ -';
2500                 
break;
2501             
/** @noinspection PhpMissingBreakStatementInspection */
2502             
case 'comment':
2503                 
// RFC 2047 section 5.2
2504                 $pattern =
'\(\)"';
2505                 
// intentional fall-through
2506                 
// for this reason we build the $pattern without including delimiters and []
2507             
case 'text':
2508             
default:
2509                 
// RFC 2047 section 5.1
2510                 
// Replace every high ascii, control, =, ? and _ characters
2511                 $pattern =
'\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern;
2512                 
break;
2513         }
2514         $matches = array();
2515         
if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) {
2516             
// If the string contains an '=', make sure it's the first thing we replace
2517             
// so as to avoid double-encoding
2518             $eqkey = array_search(
'=', $matches[0]);
2519             
if (false !== $eqkey) {
2520                 unset($matches[
0][$eqkey]);
2521                 array_unshift($matches[
0], '=');
2522             }
2523             
foreach (array_unique($matches[0]) as $char) {
2524                 $encoded = str_replace($
char, '=' . sprintf('%02X', ord($char)), $encoded);
2525             }
2526         }
2527         
// Replace every spaces to _ (more readable than =20)
2528         
return str_replace(' ', '_', $encoded);
2529     }
2530
2531
2532     
/**
2533      * Add a
string or binary attachment (non-filesystem).
2534      * This method can be used to attach ascii or binary data,
2535      * such
as a BLOB record from a database.
2536      * @param
string $string String attachment data.
2537      * @param
string $filename Name of the attachment.
2538      * @param
string $encoding File encoding (see $Encoding).
2539      * @param
string $type File extension (MIME) type.
2540      * @param
string $disposition Disposition to use
2541      * @
return void
2542      */

2543     
public function addStringAttachment(
2544         $
string,
2545         $filename,
2546         $encoding =
'base64',
2547         $type =
'',
2548         $disposition =
'attachment'
2549     ) {
2550         
// If a MIME type is not specified, try to work it out from the file name
2551         
if ($type == '') {
2552             $type = self::filenameToType($filename);
2553         }
2554         
// Append to $attachment array
2555         $
this->attachment[] = array(
2556             
0 => $string,
2557             
1 => $filename,
2558             
2 => basename($filename),
2559             
3 => $encoding,
2560             
4 => $type,
2561             
5 => true, // isStringAttachment
2562             
6 => $disposition,
2563             
7 => 0
2564         );
2565     }
2566
2567     
/**
2568      * Add an embedded (inline) attachment
from a file.
2569      * This can include images, sounds, and just about any other document type.
2570      * These differ
from 'regular' attachments in that they are intended to be
2571      * displayed inline with the message, not just attached
for download.
2572      * This
is used in HTML messages that embed the images
2573      * the HTML refers to
using the $cid value.
2574      * @param
string $path Path to the attachment.
2575      * @param
string $cid Content ID of the attachment; Use this to reference
2576      * the content
when using an embedded image in HTML.
2577      * @param
string $name Overrides the attachment name.
2578      * @param
string $encoding File encoding (see $Encoding).
2579      * @param
string $type File MIME type.
2580      * @param
string $disposition Disposition to use
2581      * @
return boolean True on successfully adding an attachment
2582      */

2583     
public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline')
2584     {
2585         
if (!@is_file($path)) {
2586             $
this->setError($this->lang('file_access') . $path);
2587             
return false;
2588         }
2589
2590         
// If a MIME type is not specified, try to work it out from the file name
2591         
if ($type == '') {
2592             $type = self::filenameToType($path);
2593         }
2594
2595         $filename = basename($path);
2596         
if ($name == '') {
2597             $name = $filename;
2598         }
2599
2600         
// Append to $attachment array
2601         $
this->attachment[] = array(
2602             
0 => $path,
2603             
1 => $filename,
2604             
2 => $name,
2605             
3 => $encoding,
2606             
4 => $type,
2607             
5 => false, // isStringAttachment
2608             
6 => $disposition,
2609             
7 => $cid
2610         );
2611         
return true;
2612     }
2613
2614     
/**
2615      * Add an embedded stringified attachment.
2616      * This can include images, sounds, and just about any other document type.
2617      * Be sure to
set the $type to an image type for images:
2618      * JPEG images use
'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'.
2619      * @param
string $string The attachment binary data.
2620      * @param
string $cid Content ID of the attachment; Use this to reference
2621      * the content
when using an embedded image in HTML.
2622      * @param
string $name
2623      * @param
string $encoding File encoding (see $Encoding).
2624      * @param
string $type MIME type.
2625      * @param
string $disposition Disposition to use
2626      * @
return boolean True on successfully adding an attachment
2627      */

2628     
public function addStringEmbeddedImage(
2629         $
string,
2630         $cid,
2631         $name =
'',
2632         $encoding =
'base64',
2633         $type =
'',
2634         $disposition =
'inline'
2635     ) {
2636         
// If a MIME type is not specified, try to work it out from the name
2637         
if ($type == '') {
2638             $type = self::filenameToType($name);
2639         }
2640
2641         
// Append to $attachment array
2642         $
this->attachment[] = array(
2643             
0 => $string,
2644             
1 => $name,
2645             
2 => $name,
2646             
3 => $encoding,
2647             
4 => $type,
2648             
5 => true, // isStringAttachment
2649             
6 => $disposition,
2650             
7 => $cid
2651         );
2652         
return true;
2653     }
2654
2655     
/**
2656      * Check
if an inline attachment is present.
2657      * @access
public
2658      * @
return boolean
2659      */

2660     
public function inlineImageExists()
2661     {
2662         
foreach ($this->attachment as $attachment) {
2663             
if ($attachment[6] == 'inline') {
2664                 
return true;
2665             }
2666         }
2667         
return false;
2668     }
2669
2670     
/**
2671      * Check
if an attachment (non-inline) is present.
2672      * @
return boolean
2673      */

2674     
public function attachmentExists()
2675     {
2676         
foreach ($this->attachment as $attachment) {
2677             
if ($attachment[6] == 'attachment') {
2678                 
return true;
2679             }
2680         }
2681         
return false;
2682     }
2683
2684     
/**
2685      * Check
if this message has an alternative body set.
2686      * @
return boolean
2687      */

2688     
public function alternativeExists()
2689     {
2690         
return !empty($this->AltBody);
2691     }
2692
2693     
/**
2694      * Clear all To recipients.
2695      * @
return void
2696      */

2697     
public function clearAddresses()
2698     {
2699         
foreach ($this->to as $to) {
2700             unset($
this->all_recipients[strtolower($to[0])]);
2701         }
2702         $
this->to = array();
2703     }
2704
2705     
/**
2706      * Clear all CC recipients.
2707      * @
return void
2708      */

2709     
public function clearCCs()
2710     {
2711         
foreach ($this->cc as $cc) {
2712             unset($
this->all_recipients[strtolower($cc[0])]);
2713         }
2714         $
this->cc = array();
2715     }
2716
2717     
/**
2718      * Clear all BCC recipients.
2719      * @
return void
2720      */

2721     
public function clearBCCs()
2722     {
2723         
foreach ($this->bcc as $bcc) {
2724             unset($
this->all_recipients[strtolower($bcc[0])]);
2725         }
2726         $
this->bcc = array();
2727     }
2728
2729     
/**
2730      * Clear all ReplyTo recipients.
2731      * @
return void
2732      */

2733     
public function clearReplyTos()
2734     {
2735         $
this->ReplyTo = array();
2736     }
2737
2738     
/**
2739      * Clear all recipient types.
2740      * @
return void
2741      */

2742     
public function clearAllRecipients()
2743     {
2744         $
this->to = array();
2745         $
this->cc = array();
2746         $
this->bcc = array();
2747         $
this->all_recipients = array();
2748     }
2749
2750     
/**
2751      * Clear all filesystem,
string, and binary attachments.
2752      * @
return void
2753      */

2754     
public function clearAttachments()
2755     {
2756         $
this->attachment = array();
2757     }
2758
2759     
/**
2760      * Clear all custom headers.
2761      * @
return void
2762      */

2763     
public function clearCustomHeaders()
2764     {
2765         $
this->CustomHeader = array();
2766     }
2767
2768     
/**
2769      * Add an error message to the error container.
2770      * @access
protected
2771      * @param
string $msg
2772      * @
return void
2773      */

2774     
protected function setError($msg)
2775     {
2776         $
this->error_count++;
2777         
if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
2778             $lasterror = $
this->smtp->getError();
2779             
if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
2780                 $msg .=
'<p>' . $this->lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n";
2781             }
2782         }
2783         $
this->ErrorInfo = $msg;
2784     }
2785
2786     
/**
2787      * Return an RFC
822 formatted date.
2788      * @access
public
2789      * @
return string
2790      * @
static
2791      */

2792     
public static function rfcDate()
2793     {
2794         
// Set the time zone to whatever the default is to avoid 500 errors
2795         
// Will default to UTC if it's not set properly in php.ini
2796         date_default_timezone_set(@date_default_timezone_get());
2797         
return date('D, j M Y H:i:s O');
2798     }
2799
2800     
/**
2801      * Get the server hostname.
2802      * Returns
'localhost.localdomain' if unknown.
2803      * @access
protected
2804      * @
return string
2805      */

2806     
protected function serverHostname()
2807     {
2808         $result =
'localhost.localdomain';
2809         
if (!empty($this->Hostname)) {
2810             $result = $
this->Hostname;
2811         } elseif (isset($_SERVER) and array_key_exists(
'SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) {
2812             $result = $_SERVER[
'SERVER_NAME'];
2813         } elseif (function_exists(
'gethostname') && gethostname() !== false) {
2814             $result = gethostname();
2815         } elseif (php_uname(
'n') !== false) {
2816             $result = php_uname(
'n');
2817         }
2818         
return $result;
2819     }
2820
2821     
/**
2822      * Get an error message
in the current language.
2823      * @access
protected
2824      * @param
string $key
2825      * @
return string
2826      */

2827     
protected function lang($key)
2828     {
2829         
if (count($this->language) < 1) {
2830             $
this->setLanguage('en'); // set the default language
2831         }
2832
2833         
if (isset($this->language[$key])) {
2834             
return $this->language[$key];
2835         }
else {
2836             
return 'Language string failed to load: ' . $key;
2837         }
2838     }
2839
2840     
/**
2841      * Check
if an error occurred.
2842      * @access
public
2843      * @
return boolean True if an error did occur.
2844      */

2845     
public function isError()
2846     {
2847         
return ($this->error_count > 0);
2848     }
2849
2850     
/**
2851      * Ensure consistent line endings
in a string.
2852      * Changes every end of line
from CRLF, CR or LF to $this->LE.
2853      * @access
public
2854      * @param
string $str String to fixEOL
2855      * @
return string
2856      */

2857     
public function fixEOL($str)
2858     {
2859         
// Normalise to \n
2860         $nstr = str_replace(array(
"\r\n", "\r"), "\n", $str);
2861         
// Now convert LE as needed
2862         
if ($this->LE !== "\n") {
2863             $nstr = str_replace(
"\n", $this->LE, $nstr);
2864         }
2865         
return $nstr;
2866     }
2867
2868     
/**
2869      * Add a custom header.
2870      * $name
value can be overloaded to contain
2871      * both header name and
value (name:value)
2872      * @access
public
2873      * @param
string $name Custom header name
2874      * @param
string $value Header value
2875      * @
return void
2876      */

2877     
public function addCustomHeader($name, $value = null)
2878     {
2879         
if ($value === null) {
2880             
// Value passed in as name:value
2881             $
this->CustomHeader[] = explode(':', $name, 2);
2882         }
else {
2883             $
this->CustomHeader[] = array($name, $value);
2884         }
2885     }
2886
2887     
/**
2888      * Create a message
from an HTML string.
2889      * Automatically makes modifications
for inline images and backgrounds
2890      * and creates a plain-text version
by converting the HTML.
2891      * Overwrites any existing values
in $this->Body and $this->AltBody
2892      * @access
public
2893      * @param
string $message HTML message string
2894      * @param
string $basedir baseline directory for path
2895      * @param boolean|callable $advanced Whether to use the
internal HTML to text converter
2896      * or your own custom converter @see html2text()
2897      * @
return string $message
2898      */

2899     
public function msgHTML($message, $basedir = '', $advanced = false)
2900     {
2901         preg_match_all(
'/(src|background)=["\'](.*)["\']/Ui', $message, $images);
2902         
if (isset($images[2])) {
2903             
foreach ($images[2] as $imgindex => $url) {
2904                 
// Convert data URIs into embedded images
2905                 
if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) {
2906                     $data = substr($url, strpos($url,
','));
2907                     
if ($match[2]) {
2908                         $data = base64_decode($data);
2909                     }
else {
2910                         $data = rawurldecode($data);
2911                     }
2912                     $cid = md5($url) .
'@phpmailer.0'; // RFC2392 S 2
2913                     
if ($this->addStringEmbeddedImage($data, $cid, '', 'base64', $match[1])) {
2914                         $message = str_replace(
2915                             $images[
0][$imgindex],
2916                             $images[
1][$imgindex] . '="cid:' . $cid . '"',
2917                             $message
2918                         );
2919                     }
2920                 } elseif (!preg_match(
'#^[A-z]+://#', $url)) {
2921                     
// Do not change urls for absolute images (thanks to corvuscorax)
2922                     $filename = basename($url);
2923                     $directory = dirname($url);
2924                     
if ($directory == '.') {
2925                         $directory =
'';
2926                     }
2927                     $cid = md5($url) .
'@phpmailer.0'; // RFC2392 S 2
2928                     
if (strlen($basedir) > 1 && substr($basedir, -1) != '/') {
2929                         $basedir .=
'/';
2930                     }
2931                     
if (strlen($directory) > 1 && substr($directory, -1) != '/') {
2932                         $directory .=
'/';
2933                     }
2934                     
if ($this->addEmbeddedImage(
2935                         $basedir . $directory . $filename,
2936                         $cid,
2937                         $filename,
2938                         
'base64',
2939                         self::_mime_types((
string)self::mb_pathinfo($filename, PATHINFO_EXTENSION))
2940                     )
2941                     ) {
2942                         $message = preg_replace(
2943                             
'/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui',
2944                             $images[
1][$imgindex] . '="cid:' . $cid . '"',
2945                             $message
2946                         );
2947                     }
2948                 }
2949             }
2950         }
2951         $
this->isHTML(true);
2952         
// Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better
2953         $
this->Body = $this->normalizeBreaks($message);
2954         $
this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced));
2955         
if (empty($this->AltBody)) {
2956             $
this->AltBody = 'To view this email message, open it in a program that understands HTML!' .
2957                 self::CRLF . self::CRLF;
2958         }
2959         
return $this->Body;
2960     }
2961
2962     
/**
2963      * Convert an HTML
string into plain text.
2964      * This
is used by msgHTML().
2965      * Note - older versions of
this function used a bundled advanced converter
2966      * which was been removed
for license reasons in #232
2967      * Example usage:
2968      * <code>
2969      * // Use
default conversion
2970      * $plain = $mail->html2text($html);
2971      * // Use your own custom converter
2972      * $plain = $mail->html2text($html, function($html) {
2973      * $converter =
new MyHtml2text($html);
2974      *
return $converter->get_text();
2975      * });
2976      * </code>
2977      * @param
string $html The HTML text to convert
2978      * @param boolean|callable $advanced Any boolean
value to use the internal converter,
2979      * or provide your own callable
for custom conversion.
2980      * @
return string
2981      */

2982     
public function html2text($html, $advanced = false)
2983     {
2984         
if (is_callable($advanced)) {
2985             
return call_user_func($advanced, $html);
2986         }
2987         
return html_entity_decode(
2988             trim(strip_tags(preg_replace(
'/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))),
2989             ENT_QUOTES,
2990             $
this->CharSet
2991         );
2992     }
2993
2994     
/**
2995      * Get the MIME type
for a file extension.
2996      * @param
string $ext File extension
2997      * @access
public
2998      * @
return string MIME type of file.
2999      * @
static
3000      */

3001     
public static function _mime_types($ext = '')
3002     {
3003         $mimes = array(
3004             
'xl' => 'application/excel',
3005             
'js' => 'application/javascript',
3006             
'hqx' => 'application/mac-binhex40',
3007             
'cpt' => 'application/mac-compactpro',
3008             
'bin' => 'application/macbinary',
3009             
'doc' => 'application/msword',
3010             
'word' => 'application/msword',
3011             
'class' => 'application/octet-stream',
3012             
'dll' => 'application/octet-stream',
3013             
'dms' => 'application/octet-stream',
3014             
'exe' => 'application/octet-stream',
3015             
'lha' => 'application/octet-stream',
3016             
'lzh' => 'application/octet-stream',
3017             
'psd' => 'application/octet-stream',
3018             
'sea' => 'application/octet-stream',
3019             
'so' => 'application/octet-stream',
3020             
'oda' => 'application/oda',
3021             
'pdf' => 'application/pdf',
3022             
'ai' => 'application/postscript',
3023             
'eps' => 'application/postscript',
3024             
'ps' => 'application/postscript',
3025             
'smi' => 'application/smil',
3026             
'smil' => 'application/smil',
3027             
'mif' => 'application/vnd.mif',
3028             
'xls' => 'application/vnd.ms-excel',
3029             
'ppt' => 'application/vnd.ms-powerpoint',
3030             
'wbxml' => 'application/vnd.wap.wbxml',
3031             
'wmlc' => 'application/vnd.wap.wmlc',
3032             
'dcr' => 'application/x-director',
3033             
'dir' => 'application/x-director',
3034             
'dxr' => 'application/x-director',
3035             
'dvi' => 'application/x-dvi',
3036             
'gtar' => 'application/x-gtar',
3037             
'php3' => 'application/x-httpd-php',
3038             
'php4' => 'application/x-httpd-php',
3039             
'php' => 'application/x-httpd-php',
3040             
'phtml' => 'application/x-httpd-php',
3041             
'phps' => 'application/x-httpd-php-source',
3042             
'swf' => 'application/x-shockwave-flash',
3043             
'sit' => 'application/x-stuffit',
3044             
'tar' => 'application/x-tar',
3045             
'tgz' => 'application/x-tar',
3046             
'xht' => 'application/xhtml+xml',
3047             
'xhtml' => 'application/xhtml+xml',
3048             
'zip' => 'application/zip',
3049             
'mid' => 'audio/midi',
3050             
'midi' => 'audio/midi',
3051             
'mp2' => 'audio/mpeg',
3052             
'mp3' => 'audio/mpeg',
3053             
'mpga' => 'audio/mpeg',
3054             
'aif' => 'audio/x-aiff',
3055             
'aifc' => 'audio/x-aiff',
3056             
'aiff' => 'audio/x-aiff',
3057             
'ram' => 'audio/x-pn-realaudio',
3058             
'rm' => 'audio/x-pn-realaudio',
3059             
'rpm' => 'audio/x-pn-realaudio-plugin',
3060             
'ra' => 'audio/x-realaudio',
3061             
'wav' => 'audio/x-wav',
3062             
'bmp' => 'image/bmp',
3063             
'gif' => 'image/gif',
3064             
'jpeg' => 'image/jpeg',
3065             
'jpe' => 'image/jpeg',
3066             
'jpg' => 'image/jpeg',
3067             
'png' => 'image/png',
3068             
'tiff' => 'image/tiff',
3069             
'tif' => 'image/tiff',
3070             
'eml' => 'message/rfc822',
3071             
'css' => 'text/css',
3072             
'html' => 'text/html',
3073             
'htm' => 'text/html',
3074             
'shtml' => 'text/html',
3075             
'log' => 'text/plain',
3076             
'text' => 'text/plain',
3077             
'txt' => 'text/plain',
3078             
'rtx' => 'text/richtext',
3079             
'rtf' => 'text/rtf',
3080             
'vcf' => 'text/vcard',
3081             
'vcard' => 'text/vcard',
3082             
'xml' => 'text/xml',
3083             
'xsl' => 'text/xml',
3084             
'mpeg' => 'video/mpeg',
3085             
'mpe' => 'video/mpeg',
3086             
'mpg' => 'video/mpeg',
3087             
'mov' => 'video/quicktime',
3088             
'qt' => 'video/quicktime',
3089             
'rv' => 'video/vnd.rn-realvideo',
3090             
'avi' => 'video/x-msvideo',
3091             
'movie' => 'video/x-sgi-movie'
3092         );
3093         
return (array_key_exists(strtolower($ext), $mimes) ? $mimes[strtolower($ext)]: 'application/octet-stream');
3094     }
3095
3096     
/**
3097      * Map a file name to a MIME type.
3098      * Defaults to
'application/octet-stream', i.e.. arbitrary binary data.
3099      * @param
string $filename A file name or full path, does not need to exist as a file
3100      * @
return string
3101      * @
static
3102      */

3103     
public static function filenameToType($filename)
3104     {
3105         
// In case the path is a URL, strip any query string before getting extension
3106         $qpos = strpos($filename,
'?');
3107         
if (false !== $qpos) {
3108             $filename = substr($filename,
0, $qpos);
3109         }
3110         $pathinfo = self::mb_pathinfo($filename);
3111         
return self::_mime_types($pathinfo['extension']);
3112     }
3113
3114     
/**
3115      * Multi-
byte-safe pathinfo replacement.
3116      * Drop-
in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe.
3117      * Works similarly to the one
in PHP >= 5.2.0
3118      * @link http://www.php.net/manual/en/function.pathinfo.php#
107461
3119      * @param
string $path A filename or path, does not need to exist as a file
3120      * @param integer|
string $options Either a PATHINFO_* constant,
3121      * or a
string name to return only the specified piece, allows 'filename' to work on PHP < 5.2
3122      * @
return string|array
3123      * @
static
3124      */

3125     
public static function mb_pathinfo($path, $options = null)
3126     {
3127         $ret = array(
'dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');
3128         $pathinfo = array();
3129         
if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) {
3130             
if (array_key_exists(1, $pathinfo)) {
3131                 $ret[
'dirname'] = $pathinfo[1];
3132             }
3133             
if (array_key_exists(2, $pathinfo)) {
3134                 $ret[
'basename'] = $pathinfo[2];
3135             }
3136             
if (array_key_exists(5, $pathinfo)) {
3137                 $ret[
'extension'] = $pathinfo[5];
3138             }
3139             
if (array_key_exists(3, $pathinfo)) {
3140                 $ret[
'filename'] = $pathinfo[3];
3141             }
3142         }
3143         
switch ($options) {
3144             
case PATHINFO_DIRNAME:
3145             
case 'dirname':
3146                 
return $ret['dirname'];
3147             
case PATHINFO_BASENAME:
3148             
case 'basename':
3149                 
return $ret['basename'];
3150             
case PATHINFO_EXTENSION:
3151             
case 'extension':
3152                 
return $ret['extension'];
3153             
case PATHINFO_FILENAME:
3154             
case 'filename':
3155                 
return $ret['filename'];
3156             
default:
3157                 
return $ret;
3158         }
3159     }
3160
3161     
/**
3162      * Set or reset instance properties.
3163      * You should avoid
this function - it's more verbose, less efficient, more error-prone and
3164      * harder to debug than setting properties directly.
3165      * Usage Example:
3166      * `$mail->
set('SMTPSecure', 'tls');`
3167      *
is the same as:
3168      * `$mail->SMTPSecure =
'tls';`
3169      * @access
public
3170      * @param
string $name The property name to set
3171      * @param mixed $
value The value to set the property to
3172      * @
return boolean
3173      * @TODO Should
this not be using the __set() magic function?
3174      */

3175     
public function set($name, $value = '')
3176     {
3177         
if (property_exists($this, $name)) {
3178             $
this->$name = $value;
3179             
return true;
3180         }
else {
3181             $
this->setError($this->lang('variable_set') . $name);
3182             
return false;
3183         }
3184     }
3185
3186     
/**
3187      * Strip newlines to prevent header injection.
3188      * @access
public
3189      * @param
string $str
3190      * @
return string
3191      */

3192     
public function secureHeader($str)
3193     {
3194         
return trim(str_replace(array("\r", "\n"), '', $str));
3195     }
3196
3197     
/**
3198      * Normalize line breaks
in a string.
3199      * Converts UNIX LF, Mac CR and Windows CRLF line breaks
into a single line break format.
3200      * Defaults to CRLF (
for message bodies) and preserves consecutive breaks.
3201      * @param
string $text
3202      * @param
string $breaktype What kind of line break to use, defaults to CRLF
3203      * @
return string
3204      * @access
public
3205      * @
static
3206      */

3207     
public static function normalizeBreaks($text, $breaktype = "\r\n")
3208     {
3209         
return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text);
3210     }
3211
3212
3213     
/**
3214      * Set the
public and private key files and password for S/MIME signing.
3215      * @access
public
3216      * @param
string $cert_filename
3217      * @param
string $key_filename
3218      * @param
string $key_pass Password for private key
3219      */

3220     
public function sign($cert_filename, $key_filename, $key_pass)
3221     {
3222         $
this->sign_cert_file = $cert_filename;
3223         $
this->sign_key_file = $key_filename;
3224         $
this->sign_key_pass = $key_pass;
3225     }
3226
3227     
/**
3228      * Quoted-Printable-encode a DKIM header.
3229      * @access
public
3230      * @param
string $txt
3231      * @
return string
3232      */

3233     
public function DKIM_QP($txt)
3234     {
3235         $line =
'';
3236         
for ($i = 0; $i < strlen($txt); $i++) {
3237             $ord = ord($txt[$i]);
3238             
if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) {
3239                 $line .= $txt[$i];
3240             }
else {
3241                 $line .=
'=' . sprintf('%02X', $ord);
3242             }
3243         }
3244         
return $line;
3245     }
3246
3247     
/**
3248      * Generate a DKIM signature.
3249      * @access
public
3250      * @param
string $signHeader
3251      * @throws phpmailerException
3252      * @
return string
3253      */

3254     
public function DKIM_Sign($signHeader)
3255     {
3256         
if (!defined('PKCS7_TEXT')) {
3257             
if ($this->exceptions) {
3258                 
throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.');
3259             }
3260             
return '';
3261         }
3262         $privKeyStr = file_get_contents($
this->DKIM_private);
3263         
if ($this->DKIM_passphrase != '') {
3264             $privKey = openssl_pkey_get_private($privKeyStr, $
this->DKIM_passphrase);
3265         }
else {
3266             $privKey = $privKeyStr;
3267         }
3268         
if (openssl_sign($signHeader, $signature, $privKey)) {
3269             
return base64_encode($signature);
3270         }
3271         
return '';
3272     }
3273
3274     
/**
3275      * Generate a DKIM canonicalization header.
3276      * @access
public
3277      * @param
string $signHeader Header
3278      * @
return string
3279      */

3280     
public function DKIM_HeaderC($signHeader)
3281     {
3282         $signHeader = preg_replace(
'/\r\n\s+/', ' ', $signHeader);
3283         $lines = explode(
"\r\n", $signHeader);
3284         
foreach ($lines as $key => $line) {
3285             list($heading, $
value) = explode(':', $line, 2);
3286             $heading = strtolower($heading);
3287             $
value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces
3288             $lines[$key] = $heading .
':' . trim($value); // Don't forget to remove WSP around the value
3289         }
3290         $signHeader = implode(
"\r\n", $lines);
3291         
return $signHeader;
3292     }
3293
3294     
/**
3295      * Generate a DKIM canonicalization body.
3296      * @access
public
3297      * @param
string $body Message Body
3298      * @
return string
3299      */

3300     
public function DKIM_BodyC($body)
3301     {
3302         
if ($body == '') {
3303             
return "\r\n";
3304         }
3305         
// stabilize line endings
3306         $body = str_replace(
"\r\n", "\n", $body);
3307         $body = str_replace(
"\n", "\r\n", $body);
3308         
// END stabilize line endings
3309         
while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") {
3310             $body = substr($body,
0, strlen($body) - 2);
3311         }
3312         
return $body;
3313     }
3314
3315     
/**
3316      * Create the DKIM header and body
in a new message header.
3317      * @access
public
3318      * @param
string $headers_line Header lines
3319      * @param
string $subject Subject
3320      * @param
string $body Body
3321      * @
return string
3322      */

3323     
public function DKIM_Add($headers_line, $subject, $body)
3324     {
3325         $DKIMsignatureType =
'rsa-sha1'; // Signature & hash algorithms
3326         $DKIMcanonicalization =
'relaxed/simple'; // Canonicalization of header/body
3327         $DKIMquery =
'dns/txt'; // Query method
3328         $DKIMtime = time();
// Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
3329         $subject_header =
"Subject: $subject";
3330         $headers = explode($
this->LE, $headers_line);
3331         $from_header =
'';
3332         $to_header =
'';
3333         $current =
'';
3334         
foreach ($headers as $header) {
3335             
if (strpos($header, 'From:') === 0) {
3336                 $from_header = $header;
3337                 $current =
'from_header';
3338             } elseif (strpos($header,
'To:') === 0) {
3339                 $to_header = $header;
3340                 $current =
'to_header';
3341             }
else {
3342                 
if ($current && strpos($header, ' =?') === 0) {
3343                     $current .= $header;
3344                 }
else {
3345                     $current =
'';
3346                 }
3347             }
3348         }
3349         $
from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
3350         $to = str_replace(
'|', '=7C', $this->DKIM_QP($to_header));
3351         $subject = str_replace(
3352             
'|',
3353             
'=7C',
3354             $
this->DKIM_QP($subject_header)
3355         );
// Copied header fields (dkim-quoted-printable)
3356         $body = $
this->DKIM_BodyC($body);
3357         $DKIMlen = strlen($body);
// Length of body
3358         $DKIMb64 = base64_encode(pack(
'H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body
3359         $ident = ($
this->DKIM_identity == '') ? '' : ' i=' . $this->DKIM_identity . ';';
3360         $dkimhdrs =
'DKIM-Signature: v=1; a=' .
3361             $DKIMsignatureType .
'; q=' .
3362             $DKIMquery .
'; l=' .
3363             $DKIMlen .
'; s=' .
3364             $
this->DKIM_selector .
3365             
";\r\n" .
3366             
"\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" .
3367             
"\th=From:To:Subject;\r\n" .
3368             
"\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" .
3369             
"\tz=$from\r\n" .
3370             
"\t|$to\r\n" .
3371             
"\t|$subject;\r\n" .
3372             
"\tbh=" . $DKIMb64 . ";\r\n" .
3373             
"\tb=";
3374         $toSign = $
this->DKIM_HeaderC(
3375             $from_header .
"\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs
3376         );
3377         $signed = $
this->DKIM_Sign($toSign);
3378         
return $dkimhdrs . $signed . "\r\n";
3379     }
3380
3381     
/**
3382      * Allows
for public read access to 'to' property.
3383      * @access
public
3384      * @
return array
3385      */

3386     
public function getToAddresses()
3387     {
3388         
return $this->to;
3389     }
3390
3391     
/**
3392      * Allows
for public read access to 'cc' property.
3393      * @access
public
3394      * @
return array
3395      */

3396     
public function getCcAddresses()
3397     {
3398         
return $this->cc;
3399     }
3400
3401     
/**
3402      * Allows
for public read access to 'bcc' property.
3403      * @access
public
3404      * @
return array
3405      */

3406     
public function getBccAddresses()
3407     {
3408         
return $this->bcc;
3409     }
3410
3411     
/**
3412      * Allows
for public read access to 'ReplyTo' property.
3413      * @access
public
3414      * @
return array
3415      */

3416     
public function getReplyToAddresses()
3417     {
3418         
return $this->ReplyTo;
3419     }
3420
3421     
/**
3422      * Allows
for public read access to 'all_recipients' property.
3423      * @access
public
3424      * @
return array
3425      */

3426     
public function getAllRecipientAddresses()
3427     {
3428         
return $this->all_recipients;
3429     }
3430
3431     
/**
3432      * Perform a callback.
3433      * @param boolean $isSent
3434      * @param array $to
3435      * @param array $cc
3436      * @param array $bcc
3437      * @param
string $subject
3438      * @param
string $body
3439      * @param
string $from
3440      */

3441     
protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from)
3442     {
3443         
if (!empty($this->action_function) && is_callable($this->action_function)) {
3444             $
params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);
3445             call_user_func_array($
this->action_function, $params);
3446         }
3447     }
3448 }

3449
3450 /**
3451  * PHPMailer exception handler
3452  * @package PHPMailer
3453  */

3454 class
phpmailerException extends Exception
3455 {
3456     
/**
3457      * Prettify error message output
3458      * @
return string
3459      */

3460     
public function errorMessage()
3461     {
3462         $errorMsg =
'<strong>' . $this->getMessage() . "</strong><br />\n";
3463         
return $errorMsg;
3464     }
3465 }



Full source code website bán hàng thương mại điện tử gần giống shopee 467.443 lượt xem

Gõ tìm kiếm nhanh...